معرفی هوک‌ها

هوک‌ها قابلیت جدیدی هستند که به نسخه ۱۶.۸ اضافه شده‌اند. با استفاده از آن‌ها می‌توانید بدون نوشتن کلاس، از state و دیگر ویژگی‌های ری‌اکت استفاده کنید.

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

تابع جدید useState اولین هوکی است که آن را یاد می‌گیریم. اگر آن را درک نمی‌کنید، نگران نباشید چون این مثال فقط برای آشنایی اولیه آورده شده‌است.

در این صفحه ما درباره این‌که چرا هوک‌ها را به ری‌اکت اضافه کردیم و چگونه با استفاده از آن‌ها می توان برنامه‌های بسیار خوبی ساخت، صحبت می‌کنیم. پس اگر می‌خواهید استفاده از هوک‌ها را یاد بگیرید، مستقیم به صفحه بعد بروید.

نکته

ری‌‌اکت ۱۶.۸.۰ اولین نسخه منتشر شده است که از هوک‌‌ها پشتیبانی می‌‌کند. هنگام ارتقاع، فراموش نکنید همه‌‌ی پکیج‌‌ها شامل React DOM را به‌روز رسانی نمایید. ری‌اکت نیتیو از زمان انتشار نسخه ۰.۵۹ از هوک‌ها پشتیبانی می‌کند.

معرفی تصویری

در کنفرانس ری‌اکت ۲۰۱۸، سوفی آلپرت (Sophie Alpert) و دن آبراموف (Dan Abramov) هوک‌ها را معرفی کردند. و در ادامه رایان فلورنس (Ryan Florence) نشان داد که چگونه می‌توان یک برنامه را بازنویسی کرد که از هوک‌ها استفاده کند. ویدیو آن را مشاهده کنید:

بدون تغییرات مخرب

قبل از ادامه، توجه داشته‌باشید که هوک‌ها:

  • کاملا اختیاری هستند. شما می‌‌توانید هوک‌‌ها را بدون نیاز به دوباره نوشتن کدهای قبلی، در چند کامپوننت جدید امتحان کنید. اما مجبور نیستید که حالا هوک‌ها را یاد بگیرید اگر تمایلی به فراگیری آن ندارید.
  • با کد‌های قدیمی ۱۰۰٪ سازگار هستند. هوک‌ها تغییرات مخربی ندارند و باعث از کار افتادن دیگر قسمت‌ها نخواهند شد.
  • از همین حالا قابل استفاده هستند. هوک‌ها هم‌اکنون ابا انتشار نسخه‌‌ی ۱۶.۸.۰ قابل استفاده هستند.

هیچ برنامه‌‌ای برای حذف کلاس‌‌ها از ری‌‌اکت وجود ندارد. شما می‌‌توانید برای مطالعه‌‌ی بیشتر در رابطه با راهکار‌‌‌‌های تطبیق تدریجی با هوک‌‌ها از بخش پایین همین صفحه استفاده کنید.

هوک‌ها جایگزین برای دانش شما از مفاهیم ری‌اکت نخواهند شد. در عوض هوک‌ها یک رابط (API) مستقیم برای مفاهیم ری‌‌اکتی که از قبل می‌‌دانید مانند props، state، context، refs و چرخه حیات فراهم می‌‌کنند. همچنین بعدا نشان خواهیم داد که چگونه هوک‌‌ها روشی جدید و قدرتمند برای تلفیق آن‌‌ها ارائه می‌‌کنند.

اگر هم‌‌اکنون می‌‌خواهید یادگیری هوک‌‌ها را شروع کنید، مستقیم به صفحه‌‌ی بعد بروید! البته می‌‌توانید مطالعه‌‌ این صفحه را ادامه دهید و با دلایلی که هوک‌‌ها را به ری‌‌اکت اضافه کردیم و اینکه چگونه بدون بازنویسی اپلیکیشن‌‌های قبلی از آن‌‌ها استفاده خواهیم کرد، آشنا شوید.

انگیزه

هوک‌ها مشکلات مختلفی که ظاهرا به هم ارتباط ندارند را حل می‌کنند. مواردی که ما طی در نوشتن و نگهداری هزاران کامپوننت طی پنج سال با آن مواجه شده‌ایم. اگر درحال یادگیری ری‌اکت هستید، هروز از آن استفاده می‌کنید یا از کتابخانه مشابهی استفاده می‌کنید که بر پایه کامپوننت طراحی شده‌است، احتمالا به این مشکلات بر خورد کرده‌اید.

استفاده از منطق وابسته به state میان چند کامپوننت دشوار است

ری‌‌اکت راهی برای «اضافه‌کردن» یک رفتار با قابلیت استفاده‌‌ی مجدد یه یک کامپوننت را فراهم نمی‌‌کند (برای مثال اتصال به یک store). اگر شما مدتی با ری‌‌اکت کار کرده باشید، ممکن است با الگوهایی مانند render props و higher-order components آشنا شده‌باشید که سعی کرده‌اند حل این مسئله را حل کنند. اما این الگوها شما را مجبور به طراحی مججد ساختار کامپوننت، هنگام استفاده‌‌ از آن‌‌ها می‌‌کنند، که این مسئله فهم کد را دشوارتر می‌کند. اگر به یک اپلیکیشن ری‌‌اکت معمول در React DevTools نگاه کنید، احتمالا با جهنمی از کامپوننت‌های تودرتو (wrapper hell) مواجه می‌شوید. کامپوننت‌هایی که توسط لایه‌های provider، consumer، higher-order component، render props و دیگر لایه‌هایی برای ایحاد abstraction احاطه شده‌اند. اگرچه ما می‌توانستیم آن‌ها را هنگام نمایش فیلتر کنیم، این موضوع به مشکلی ریشه‌ای اشاره می‌کند: ری‌اکت نیازمند زیرساخت بهتری برای اشتراک منطق‌های وابسته به state میان کامپوننت‌ها است.

با استفاده از هوک‌ها، شما می‌توانید منطق وابسته به state را از یک کامپوننت جدا، به طور مستقل تست و چندین جا استفاده کنید. هوک‌ها به شما اجازه می‌دهند که منطق وابسته به state را بدون تغییر در طراحی سلسله مراتب کامپوننت‌ها، هربار مجددا استفاده کنید. با این ویژگی می‌توان هوک‌ها را میان کامپوننت‌ها و حتی برای جامعه توسعه‌دهندگان به اشتراک گذاشت.

درباره این موضوع در صفحه هوک‌های خودتان را بسازید بیشتر صحبت خواهیم کرد.

فهمیدن کامپوننت‌های پیچیده دشوار می‌شود

ما معمولا مجبور به نگه‌‌داری از کامپوننت‌‌هایی بودیم که در اپتدا ساده بودند اما وقتی رشد کردند، منطق‌های دارای state و side effectهایی به آن‌ها اضافه شد که مدیریت آن‌ها را مشکل می‌کرد. در هر تابع lifecycle منطق‌هایی وجود دارد که با هم ارتباطی ندارند. برای مثال، یک کامپوننت ممکن است در componentDidMount و componentDidUpdate برای دریافت داده درخواست ارسال کند. درحالی‌‌که همان تابع componentDidMount می‌‌تواند دارای منطقی غیر مرتبط باشد که به اضافه کردن event listenerها می‌‌پردازد، و در متد componentWillUnmount آن‌‌ها [event listenerها] را پاکسازی (cleanup) می‌‌کند. کدهایی که متقابلا به هم مرتبط هستند [مثل اضافه و پاک‌‌سازی event listener] از یکدیگر جدا هستند، ولی کدهایی که کاملا غیر مرتبط‌‌اند [اضافه کردنevent listener و دریافت داده] در یک متد نوشته می‌‌شوند. که این احتمال خطا و باگ و بی‌ثباتی را بیشتر می‌‌کند.

در بسیاری از موارد امکان این وجود ندارد که بتوانیم این کامپوننت‌‌ها را به اجزای کوچکتر تقسیم کنیم، زیرا منطق دارای state در همه جا وجود دارد. همچنین تست کردن آن‌‌ها دشوار است. این یکی از دلایلی است که بسیاری از افراد ترجیح می‌‌دهند تا ری‌‌اکت را با یک کتابخانه‌‌ی مدیریت state دیگری ترکیب کنند. اگرچه، معمولا باعث اضافه‌‌شدن مقدار زیادی abstraction می‌‌شود و شما را مجبور می‌‌کند بین تعداد زیادی از فایل‌‌ها جابه‌‌جا شوید که خود باعث مشکل‌‌تر شدن استفاده‌‌ی مجدد از کامپوننت‌‌ها می‌‌گردد.

برای حل این مسیله، هوک‌‌ها به شما اجازه می‌‌دهند یک کامپوننت را به توابع کوچکتری تقسیم کنید که مبنای آن ارتباط اجزایشان است (مثلا اضافه کردن یک subscription یا دریافت داده)، نه تقسیم بر اساس متدهای lifecycle. همچنین می‌‌توانید برای مدیریت state محلی از یک reducer کمک بگیرید تا آن را بیشتر قابل پیش‌بینی کنید.

در صفحه استفاده از هوک effect. بیشتر در این‌باره صحبت می‌کنیم.

کلاس‌‌ها هم انسان و هم کامپیوتر را گیج می‌‌کنند

علاوه‌بر اینکه کلاس‌ها استفاده مجدد کد‌ها و مدیریت آن‌ها را دچار مشکل می‌کنند، دریافتیم که آن‌ها می‌‌توانند مانع بزرگی در یادگیری ری‌‌اکت باشند. شما باید یادبگیرید که this چگونه در جاوااسکریپت کار می‌‌کند، که با کارکرد آن در بیشتر زبان‌‌ها بسیار متفاوت است. شما باید به یاد داشته باشید تا event handlerها را bind کنید. بدون پلاگین پیشنهاد برای نوشتن propertyهای یک کلاس (هنوز پایدار نیست!)، کد بسیار طولانی خواهد بود. آدم‌‌ها می‌‌توانند props، state، و جریان بالا به پایین داده را کاملا دریابند درحالی‌که هنوز با کلاس‌‌ها کلنجار می‌روند. در مقایسه بین کامپوننت از جنس تابع یا کلاس و موارد استفاده از آن‌‌ها، حتی بین توسعه‌دهنده‌های با تجربه‌‌ی ری‌‌اکت هم اختلاف‌نظر وجود دارد.

افزون بر این، ری‌‌اکت ۵ سال است که عرضه شده است، و ما می‌‌خواهیم در ۵ سال آینده هم مطرح باشد. همانطور که Svelte ،Angular، Glimmer و دیگران نشان می‌‌دهند، کامپایل پیش از موعد (ahead-of-time compilation) کامپوننت‌‌ها، پتانسیل زیادی را دارد. مخصوصا اگر به templateها محدود نباشد. ما اخیرا با component folding بوسیله‌‌ی Prepack‌‌ ‌‌آزمایشاتی را انجام دادیم که شاهد نتایج سریع و امیدوارکننده‌ای بوده‌‌ایم. اگرچه دریافتیم که کامپوننت‌‌های برپایه کلاس می‌‌توانند ناخواسته باعث افزایش الگوهایی شوند که چنین بهینه‌‌سازی‌‌هایی را خراب می‌‌کنند. کلاس‌‌ها برای ابزارهای امروزی نیز مشکلاتی ایجاد می‌‌کنند. برای مثال، کلاس‌‌ها به خوبی minify نمی‌‌شوند، همچنین باعث می‌‌شوند تا hot reloading شکننده و نامطمئن شود. ما می‌‌خواهیم APIای را ارائه دهیم که به کد امکان بهینه‌‌سازی بیشتری بدهد.

برای حل این مشکلات، هوک‌‌ها به شما اجازه می‌‌دهند تا از بیشتر قابلیت‌‌های ری‌‌اکت بدون کلاس‌‌ها بهره ببرید. از نظر مفهومی، همیشه کامپوننت‌‌های ری‌‌اکت بیشتر به توابع نزدیک‌‌ بوده‌‌اند. هوک‌‌ها بدون آنکه روح کاربردی ری‌‌اکت را فداکند، از توابع بهره می‌برند. استفاده از هوک‌ها ساده است و شما به یادگیری مهارت‌های پیچیده برنامه نویسی تابع‌گرا (functional) و واکنش‌گرا (reactive) ندارید.

مثال‌ها

برای شروع یادگیری، هوک‌ها در یک نگاه انتخاب مناسبی است.

راهبرد پذیرش هوک‌ها به صورت تدریجی

کوتاه بگوییم: برنامه‌ای برای حذف کلاس‌ها از ری‌اکت نیست.

ما می‌‌دانیم که توسعه‌دهنده‌های ری‌‌اکت روی عرضه‌‌ی محصولات تمرکز دارند و وقتی برای مطالعه‌ هر API جدیدی که منتشر می‌‌شود را ندارند. هوک‌‌ها خیلی تازه هستند، و شاید برای یادگیری و بهره‌‌گیری از آن‌‌ها بهتر باشد تا برای مثال‌‌ها و آموزش‌‌های بیشتر صبر کنید.

ما همچنین اطلاع داریم که انتظارات برای اضافه کردن دستورات پایه‌‌ی جدید به ری‌‌اکت بسیار بالاست. ما برای خواننده‌‌های کنجکاو، یک RFC با جزییات آماده کرده‌‌ایم که با عمق بیشتری به ایده‌ها می‌‌پردازد، و چشم‌انداز گسترده‌ای بر تصمیمات مشخصی در طراحی فعلی و پیشین فراهم می‌‌کند.

اساسا، هوک ها در کنار کدهای نوشته‌‌شده از قبل کار خواهند کرد، پس شما می‌‌توانید به‌صورت تدریجی از آن‌‌ها بهره گیرید. عجله‌ای برای مهاجرت‌ به هوک‌ها نیست! ما پیشنهاد می‌کنیم که از بازنویسی‌های کلان کد خود، به خصوص کامپوننت‌هایی پیچیده‌ای که با کلاس نوشته شده‌اند. تفکر به شیوه هوک‌ها نیازمند کمی تغییر در شیوه تفکر است. بر اساس تجربه ما، بهتر است که استفاده از هوک‌ها را در کامپوننت‌های کم اهمیت تمرین کنید و مطمئن شوید که همه اعضای تیم با آن‌ها مشکلی ندارند. بعد از اینکه هوک‌ها را امتحان کردید، بازخورد‌های خود را برای ما ارسال کنید، چه مثبت، چه منفی!

ما قصد داریم تمام موارد کاربرد کلاس‌ها رو برای هوک‌ها هم پیاده‌سازی کنیم، اما ما برای آینده قابل پیش‌بینی‌ای از کامپوننت‌های نوشته‌شده با کلاس پشتیبانی می‌کنیم. در فیس‌بوک ما ده‌ها هزار کامپوننت برپایه کلاس داریم و قطعا برنامه‌ای برای بازنویسی مجدد آن‌ها نداریم. درعوض، در کنار کلاس‌ها، استفاده از هوک‌ها را در کد‌های جدید شروع کرده‌ایم.

سوالات متداول

ما یک صفحه سوالات متداول هوک‌ها آماده کرده‌ایم که به بیشتر سوالات شما درباره هوک‌ها جواب می‌دهد.

گام‌های بعدی

در انتهای این صفحه، شما باید ایده‌ای کلی از این‌که هوک‌ها چه مشکلی را حل می‌کنند به دست آورده باشید، اما احتمالا هنوز جزییات برای شما واضح نیست. نگران نباشید! حالا بیایید به صفحه بعد برویم و یادگیری هوک‌ها رو با مثال شروع کنیم.