هوک در ریاکت چیست؟ راهنمای کامل آموزش پیادهسازی Hook در React
در این مقاله میخوانید
در برنامهنویسی React، کامپوننتهای تابعی بسیار کاربردی هستند؛ ولی قابلیت این کامپوننتها دقیقاً محدود به چیزی است که برای آنها تعریف شده است. بههمیندلیل، گاهی بهناچار باید کامپوننتهایمان را در قالب یک کلاس بنویسیم. بااینحال، خوشبختانه روشی وجود دارد که میتواند بعضی از قابلیتهای کامپوننتهای تابعی و کلاسی را توأمان داشته باشد و آن چیزی نیست جز هوک (Hook). در این مطلب، شما را با هوک در ریاکت آشنا خواهیم کرد؛ پس تا پایان با ما همراه باشید.
هوک در ریاکت چیست؟
هوکها قابلیتهای جدیدی هستند که از نسخه 16.8.0 ریاکت به آن اضافه شدند. این روشها به ما کمک میکنند تا بتوانیم قابلیتهای ریاکت مثل State و چرخه حیات (Lifecycle) را به راحتترین شکل ممکن و بدون نیاز به کلاسها به کامپوننتهای تابع اضافه کنیم.
نکته: از هوکها نمیتوان در کلاسها استفاده کرد!
چگونه هوک را در کدهای React پیادهسازی کنیم؟
برای اضافهکردن هوک به کدهای React، میتوانید از کدهای زیر استفاده کنید. دقت کنید که در این کدها باید یک نسخه React را حتماً مشخص کنید:
# Via npm $ npm install --save react@next react-dom@next # Or via Yarn $ yarn add react@next react-dom@next
قوانین کلی نوشتن هوکها
بهطورکلی، در نوشتن کدهای هوک باید به چند نکته دقت کنید:
- هوکها باید با کلمه «Use» شروع شوند.
- هوکها را فقط میتوان از کامپوننتهای توابع و از هوکهای سفارشی فراخواند. این ویژگی را میتوان مزیتی مهم دانست؛ چون باعث ایجاد منطق گروهی بین همه کامپوننتهای شما میشود.
- از هوک فقط باید در سطح بالای کدهایتان استفاده کنید، نه داخل دستورهای شرطی و حلقهای یا توابع تودرتو که در کامپوننتهای توابع دارید. با این کار مطمئن خواهید بود که هوکها با همان ترتیب و براساس هر رندر فراخوانی میشوند.
مقداردهی State کامپوننتها با هوک در ریاکت
اگر بخواهیم بهکمک hook در react کامپوننت تابعی از نوع Stateful بسازیم، باید با دستور «useState» از React package ،State مدنظر را مقداردهی کنیم. این روش یک پارامتر را برای تنظیم State اولیه میگیرد و دو چیز را برمیگرداند: یکی آرایهای حاوی State فعلی و دیگری تابعی برای تنظیم State.
در کدهای زیر، یک کامپوننت تابع از نوع Stateful داریم که با هربار کلیک، رنگی را ردیابی میکند که بهطور تصادفی سِت شده است:
import React, { useState } from "react"; import { render } from "react-dom"; function StatefulFn() { const [color, setColor] = useState(false); function onClick() { const colors = [ "#008F68", "#6DB65B", "#4AAE9B", "#FAE042", "#EFBB35", "#DFA612" ]; setColor(colors[Math.floor(Math.random() * colors.length)]); } return ( <button onClick={onClick} style={{ backgroundColor: color }}> Click to Change Button Color </button> ); } const container = document.createElement("div"); document.body.appendChild(container); render(<StatefulFn />, container);
شیوه useState طوری طراحی شده است که بتواند با مقدار واحد استفاده شود، نه با شیء State (یعنی برخلاف سازوکار کامپوننتهای Class). بههمیندلیل، یا باید خودمان بهصورت دستی شیء State را حفظ کنیم یا به روشی سادهتر فقط یک بار useState را فراخوانی کنیم تا هریک از متغیرها را در State خود ردیابی کنیم:
const [color, setColor] = useState(false); const [size, setSize] = useState('medium'); const [reptile, setReptile] = useState('alligator');
فعالکردن چرخه حیات کامپوننتها با هوک در React
یکی دیگر از مشکلات استفاده از کامپوننتهای تابع، نبود روشهای چرخه حیات (Lifecycle) برای آنهاست. این در حالی است که بخش دیگری از قابلیتهای هوک اضافهشدن «useEffect» است. useEffect ترکیبی است از componentDidUpdate و componentDidMount و componentWillUnmount. بهعبارتدیگر، useEffect بعد از رندر اولیه و هر رندر دیگری که بعداً اتفاق میافتد، فعال میشود.
اگر با چرخه حیات کامپوننتهای React آشنا باشید، میدانید که این تصمیم درستی نیست که کدهای دارای عوارض جانبی را در شیوه رندر بگنجانیم. درواقع، فلسفه وجود روشهای چرخه حیات جلوگیری از همین مسئله بوده است.
یکی از این عوارض جانبی، ارسال درخواست شبکه و بعد بهروزرسانی State با مقداری است که برگردانده میشود. در مثال زیر، با «setTimeout» اتصال شبکه بسیار کُند را شبیهسازی میکنیم. درضمن، پیامی را هم تا زمانی که کاربر باید منتظر باشد، نشان میدهیم:
import React, { useEffect, useState } from "react"; import { render } from "react-dom"; function EffectedFn() { const [loading, setLoading] = useState(true); useEffect(() => { setTimeout(() => { setLoading(false); }, 1000 * 10); }); return ( <div> {loading && <span>Loading...</span>} {!loading && <span>All Done!</span>} </div> ); } const container = document.createElement("div"); document.body.appendChild(container); render(<EffectedFn />, container);
نکته جذاب درباره useEffect این است که برخلاف componentDidMount و componentDidUpdate، مرورگر را بلاک نمیکند؛ بنابراین، میتوانید مطمئن باشید که محتواهایتان بهصورت ریسپانسیو و سریع به کاربران نشان داده میشود.
شایان ذکر است که برای بهبود عملکرد هوک در React، بهخصوص موقع کار با متغیرهای چندحالته (Multiple State)، میتوانید به useEffect بگویید که فقط وقتی فعال شود که مقدار خاصی تغییر داده میشود. برای این کار، باید از کدهای زیر استفاده کنید:
useEffect(() => { setTimeout(() => { setLoading(false); }, 1000 * 10); }, [loading]);
جمعبندی
اگر از ردوبدلکردن توابع بین کلاسها، بهویژه هنگام نیاز به پشتیبانی از State و Lifecycle خسته شدهاید، از هوک در ریاکت میتوانید کمک بگیرید تا کارتان را بهمراتب راحتتر کنید. بخش جذاب ماجرا اینجاست که میتوانید خودتان هوکهای منحصربهفردی را توسعه دهید و نیز از مجموعه وسیع هوکهایی استفاده کنید که توسعهدهندگان React ایجاد کردهاند.
سؤالات متداول
۱. کدام نسخههای React شامل هوکها هستند؟
هوکها از نسخه 16.8.0 ریاکت به آن اضافه شدند و درحالحاضر، در نسخههای زیر عملکرد پایداری دارند:
- React DOM
- React Native
- React DOM Server
- React Test Renderer
- React Shallow Renderer
۲. آیا در نسخههای جدیدتر React، استفاده از هوک ضروری خواهد بود؟
خیر، نکته مهم درباره هوک در React این است که تا وقتی خودتان نخواهید، هیچ الزامی برای استفاده از آن وجود ندارد. بنابراین، تا وقتی کار با کلاسها را ترجیح دهید، با همان روش میتوانید کار را پیش ببرید.
۳. آیا برای اضافهکردن هوک به کدها، باید همه توابع قبلی را بهروزرسانی کنیم؟
خیر، هوکها با تمام قوانین و عملکردهای قبلی سازگارند؛ بههمیندلیل، وقتی آنها را به کدهایتان اضافه میکنید، نیازی نیست که کدهای قبلی را بهروزرسانی کنید.
۴. برای اضافهکردن هوکها، بهتر است کلاسهای قبلی را هم به هوک تبدیل کنیم؟
خیر، پیشنهاد ما این است که از هوکها فقط برای نوشتن کامپوننتهای جدید استفاده کنید و کاری به کلاسهای قبلی نداشته باشید؛ مگر وقتی که بهدلایل دیگر لازم است کلاسهای قبلی را بازنویسی کنید (مثلاً برای دیباگکردن). در این صورت، بهتر است که آن کلاسها را هم در قالب هوک بنویسید.
۵. آیا میتوانیم هوکها را داخل کلاسها بنویسیم؟
خیر، نمیتوانید یک هوک را داخل کامپوننتهای یک کلاس بنویسید؛ اما میتوانید کلاسها و کامپوننتهای توابع را با هوکها در یک درخت واحد ترکیب کنید.