مقدمه
به فصل دهم خوش آمدید! تاکنون، هوک useState ابزار اصلی ما برای مدیریت وضعیت در کامپوننتها بوده
است. useState برای stateهای ساده (مانند یک عدد، رشته یا مقدار بولی) و حتی برای اشیاء و
آرایههای نه چندان پیچیده، فوقالعاده است. اما با رشد اپلیکیشن، گاهی اوقات منطق بهروزرسانی
state بسیار پیچیده میشود. برای مثال، ممکن است چندین عمل مختلف وجود داشته باشد که همگی یک شیء
state را به روشهای متفاوتی تغییر میدهند.
در این سناریوها، قرار دادن تمام منطق بهروزرسانی در داخل event handler ها میتواند کامپوننت را
شلوغ و درک آن را دشوار کند. برای حل این مشکل، React یک هوک جایگزین به نام useReducer ارائه
میدهد. useReducer به ما اجازه میدهد تا منطق بهروزرسانی state را از کامپوننت جدا کرده و آن
را در یک تابع مجزا به نام «کاهنده» یا reducer متمرکز کنیم.
useReducer چیست؟
هوک useReducer یک جایگزین برای useState است که از الگوی مدیریت وضعیت محبوب در کتابخانههایی
مانند Redux الهام گرفته شده است. این هوک زمانی مفید است که شما یک state پیچیده با چندین
انتقال وضعیت مختلف دارید.
ساختار useReducer
useReducer دو آرگومان اصلی میگیرد و یک آرایه با دو عضو برمیگرداند:
- تابع reducer: تابعی که منطق بهروزرسانی state را در خود دارد. این تابع state
فعلی و یک «اکشن» (action) را دریافت کرده و state بعدی را برمیگرداند.
- state اولیه: مقدار اولیه برای state.
خروجی آن نیز شامل state فعلی و یک تابع dispatch است.
JAVASCRIPT (React)
const [state, dispatch] = useReducer(reducer, initialState);
تابع dispatch تنها راه برای بهروزرسانی state است. شما یک «اکشن» را به این تابع dispatch
میکنید، و React state فعلی و آن اکشن را به تابع reducer شما پاس میدهد. reducer شما
state بعدی را محاسبه کرده و برمیگرداند و React کامپوننت را با state جدید دوباره رندر
میکند.
مثال کاربردی: یک شمارنده پیچیده
بیایید یک شمارنده بسازیم که علاوه بر افزایش، قابلیت کاهش و ریست شدن را نیز داشته باشد. ما این
منطق را با useReducer پیادهسازی خواهیم کرد.
۱. تعریف reducer
ابتدا، تابع reducer را تعریف میکنیم. این تابع معمولاً خارج از کامپوننت تعریف میشود.
JAVASCRIPT (React)
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
throw new Error();
}
}
تابع reducer ما یک شیء state و یک شیء action را میگیرد. شیء action معمولاً یک پراپرتی
type دارد که نوع بهروزرسانی را مشخص میکند. بر اساس این type، ما state جدید را محاسبه
کرده و برمیگردانیم.
۲. استفاده از useReducer در کامپوننت
حالا از این reducer در کامپوننت خود استفاده میکنیم.
JAVASCRIPT (React)
import { useReducer } from 'react';
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</>
);
}
در این کامپوننت، ما useReducer را با reducer خود و یک state اولیه فراخوانی میکنیم. سپس در
event handler های دکمهها، تابع dispatch را با اکشنهای مختلف فراخوانی میکنیم. این کار باعث
میشود که منطق بهروزرسانی state به صورت کاملاً تمیز و جدا از UI کامپوننت مدیریت شود.
در این درس، با هوک useReducer به عنوان یک ابزار قدرتمند برای مدیریت stateهای پیچیده آشنا
شدیم. دیدیم که چگونه میتوان با جداسازی منطق بهروزرسانی در یک تابع reducer، کامپوننتهای
خواناتر و قابل نگهداریتری نوشت.
useReducer به خصوص در اپلیکیشنهای بزرگ که در آنها state بعدی به state قبلی بستگی دارد و
چندین نوع بهروزرسانی وجود دارد، بسیار مفید است. در درس بعدی، به «مدیریت وضعیت پیچیده با
reducer» با جزئیات بیشتری خواهیم پرداخت و نحوه ارسال دادههای اضافی (payload) به reducer را
بررسی خواهیم کرد.