هوک useReducer ری اکت و بررسی تخصصی useReducer

·

7 min read

هوک useReducer رو میشه به عنوان یک جایگزین برای هوک useState در نظر گرفت ! در واقع هوک useReducer به ما کمک میکنه تا State های پیچیده تر کامپوننت های خودمون رو بتونیم مدیریت کنیم !

اگه State شما سادس ، همون هوک useState کاملا جوابگوی نیاز شماست اما اگه State های پیچیده تری دارید بهتره که از هوک useReducer ری اکت استفاده کنید.

ترکیب useReducer و useContext یک جایگزین عالی برای Redux و MobX !

اگه هوک useReducer رو با هوک useContext ترکیب کنید میشه گفت دیگه نیازی به State Managment هایی مثل Redux یا MobX ندارید!

گاهی اوغات توی اپیکیشن های ری اکتی خودمون یکسری State های Global داریم. معمولا برای مدیریت این State های Global از کتابخانه هایی مثل Redux ، MobX و Recoil استفاده میکنیم .

اما میشه با ترکیب useReducer و useContext این State های Global رو بطور مناسبی مدیریت کرد که دیگه نیازی به استفاده از Redux و سایر State Managment ها نداشته باشیم .

البته ناگفته نماند که این موضوع کاملا بستگی به پروژه شما و نوع State های Global شما دارد.

هوک useReducer ری اکت چیست ؟

درواقع هوک useReducer برای ذخیره کردن یک مقدار و بروزرسانی اون مقدار استفاده میشه . ( مثل هوک useState )

هوک useReducer دوتا آرگومان ورودی از ما دریافت میکنه :

  • اولین آرگومان یک تابع reducer هست که برای بروزرسانی مقدار ذخیره شده کاربرد داره .
  • دومین آرگومان یک مقدار اولیه ( Initial State ) هست .

هوک useReducer یک آرایه Return میکنه داخل این آرایه 2 چیز وجود داره :

  • مقدار فعلی State
  • یک تابع Dispatch که میتونیم از این تابع برای بروزرسانی مقدار State استفاده کنیم ( با پاس دادن یک Action به این Dispatch )

طبق صحبت هایی که تا الان کردیم ، هوک useReducer همون کاری رو انجام میده که Redux ( یک کتابخانه برای مدیریت State ) انجام میده با چند تفاوت. اما چون قصد نداریم در این مقاله به Redux بپردازیم فقط به این نکته اشاره میکنیم که مدیریت State های Global با useReducer خیلی ساده تر است اما Redux برای مدیریت State های بسیار پیچیده و سنگین مناسبتر است.

تابع Reducer در useReducer

گفتیم که هوک useReducer یک تابع reducer از ما میگیره . اما این تابع دقیقا چیه ؟

خیلی ساده بخوایم reduce رو توضیح بدیم میتونیم اون رو مثل یک دستگاه قهوه ساز در نظر بگیریم :

دستگاه قهوه ساز از شما پودر قهوه میگیره ، بهش آب داغ اضافه میکنه و قهوه تحویل شما میده 🙂 تابع reducer از شما State قبلی رو میگیره ، یکسری عملیات روش انجام میده و State جدید رو تحویل شما میده.

هوک useReducer ری اکت مشابه همین کار رو انجام میده. هوک useReducer یک تابع reducer از ما دریافت میکنه و یک مقدار به ما Return میکنه.

تیکه کد زیر یک مثال ساده از نحوه استفاده از هوک useReducer در ری اکت هست :

const [count, dispatch] = useReducer(reducer, initialState);

تو مثال بالا به هوک useReducer دو مقدار پاس دادیم ( تابع reducer و مقدار اولیه State )

خود تابع reducer ، دو مقدار از ما میگیره و یک مقدار رو Return میکنه .

اولین مقدار State فعلی و دومین مقدار Action ما هست ( منظور از Action کاری هست که میخوایم انجام بدیم مثل اضافه کردن ، کم کردن و ..)

یعنی تابع reducer باید بصورت زیر باشه :

const reducer=(state, action)=> { }

dispatch({ type: 'increment' })

در واقع تابع reducer بر اساس نوع action ارسال شده بهش ، کارهایی که باید رو انجام میده.

مثلا تو خط 3 بهش گفتیم increment ، پس داخل تابع reducer باید مشخص کنیم که اگر Action ما Increment بود چه اتفاقی بیوفته ( مثلا مقدار count زیاد بشه )

مقدار InitialState در useReducer

دومین آرگومانی که باید به هوک useReducer پاس بدیم ، InitialState یا همون مقدار اولیه State هست .

تو مثال زیر این کار رو انجام دادیم:

const initialState = { count: 1 }

const [state, dispatch] = useReducer(reducer, initialState)

تو اولین خط تیکه کد بالا ، یک Object داریم که این Object رو به عنوان مقدار اولیه به هوک useReducer دادیم.

متود dispatch در useReducer

معادل فارسی عبارت dispatch ، اعزام هست. زمانیکه میخوایم یک کار ( action ) اتفاق بیوفته ، تابع dispatch رو صدا میزنیم .

خود تابع dispatch به عنوان ورودی از ما یک Object میگیره که نوع کار رو مشخص میکنه. در حقیقت Action توسط متود dispatch به reducer میرسه .

خود اکشنی که به reducer میفرستیم ، مشخص کننده نوع کار هست . در حقیقت داخل تابع reducer مشخص کردیم که برای هر نوع Action چه اتفاق هایی باید بیوفته .

پس از انجام عملیات dispatch با Action مدنظرمون ، Reducer کارها و محاسباتش رو انجام میده و نتیجه رو Return میکنه .

Action شما باید یک Object باشه که شامل 2 مقدار Key و Payload باشه :

const INCREMENT={
    type : "INCREMENT",
    payload: null,
}

تو تیکه کد بالا یک Action نمونه رو میتونید ببینید . مقدار type مشخص کننده نوع کاری هست که میخوایم با dispatch کردن اون Action انجامش بدیم.

داخل payload هم میتونیم اطلاعات مورد نیاز اون Action رو بریزیم. مثلا اگر یک Action برای ثبت نام کاربر داشته باشیم ، داخل payload اطلاعات کاربر رو میتونیم بریزیم مثل نام و فامیل شخص .

تو تیکه کد زیر یک مثال براتون آماده کردم که از هوک useReducer برای ذخیره یک عدد استفاده کردیم.

یک Action برای Reset کردن مقدار ذخیره شده داریم و یک Reducer که وظیفه دریافت Action ،انجام عملیات و return کردن مقدار جدید رو داره.

یک مثال از هوک ()useReducer در React

// reducer Function
function reducer(state, action) {
  switch (action.type) {
   // ...
      case 'reset':
          return { count: action.payload };
    default:
      throw new Error();
  }
}
const initialCount = 0;
// use useReducer and set reducer,initialState to it
const [state, dispatch] = useReducer(reducer, initialCount, initFunc);

// Updating State With Dispatch reset Action
<button onClick={() => dispatch({type: 'reset', payload: initialCount})}> Reset </button>

تو خط 13 تیکه کد بالا ، با استفاده از هوک useReducer در React یک state برای ذخیره مقدار و یک dispatch برای بروزرسانی مقدار ایجاد کرده ایم .

به useReducer یک مقدار اولیه دادیم به نام initialCount که مقدارش 0 هست.

همچنین به useReducer یک تابع دادیم که وظیفه بررسی Action های ارسال شده بهش و Return مقدار جدید رو داره ( این تابع در خط 2 ایجاد شده )

تو تابع reducer ، مقدار action.type رو چک کردیم که بتونیم با توجه به نوع action تصمیم مناسب رو بگیریم . در اینجا گفتیم اگر اکشن ما reset بود ، مقداری که داخل payload برامون فرستاده شده رو برای count قرار بده. ( چون داخل payload برای ما initialCount فرستاده شده پس مقدار 0 اینجا قرار میگیره و در نتیجه مقدار state ریست میشه )

تو خط 16 هم یک دکمه برای reset کردن قرار دادیم و گفتیم اگر روی این دکمه کلیک شد ، Action مشخص شده رو dispatch کن.

تو خط 16 (هنگام dispatch ) علاوه بر مشخص کردن action type ، یک action payload هم مشخص کردیم که برای reducer فرستاده بشه.

شعور ()useReducer !

هوک useReducer باشعوره . اگه مقداری که useReducer برمیگردونه ( return میکنه ) با مقدار فعلی state برابر باشه ، هیچ رندر مجددی صورت نمیگیره .

یه مثال کامل از هوک useReducer ری اکت

خب حالا که با هوک useReducer آشنا شدین ، بریم یه مثال کامل ازش ببینیم .

تو این مثال میخوایم یه Counter App بسازیم.

میخوایم 3 تا دکمه برای افزایش مقدار ، کاهش مقدار و ریست مقدار داشته باشیم :

import React, { useReducer } from 'react';

const initialState = { count: 0 }
 // The reducer function
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: state.count = 0}
    default:
     return { count: state.count  }
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    <div>
      مقدار فعلی : {state.count}
       <br />
       <br/>
       <button onClick={() => dispatch({ type: 'increment' })}> افزایش </button>
       <button onClick={() => dispatch({ type: 'decrement'})}> کاهش </button>
       <button onClick={() => dispatch({ type: 'reset'})}> ریست </button>
    </div>
  );
};

export default Counter;

تو مثل بالا 3 تا دکمه داریم که با کلیک کردن روی هرکدوم یک Action رو Dispatch میکنیم.

دکمه افزایش برای increment کردن ، دکمه کاهش برای decrement کردن و دکمه reset برای ریست مقدار.

تو خط 19 یک مقدار اولیه ( initialState ) مشخص کردیم که مقدارش 0 هست. همچنین یک تابع reducer مشخص کردیم .

این تابع reducer در خط 5 تعریف شده و وظیفش بررسی کردن نوع Action ( توسط Switch ) هست و با توجه به نوع Action مقدار فعلی رو تغییر میده و مقدار جدید رو Return میکنه.

ما اینجا 3 نوع Action داریم ( increment,decrement,reset ) ولی ممکنه شما نیاز به Action های بیشتر با قابلیت های بیشتری داشته باشید .

اما بریم سراغ یه سوال پرتکرار که تو مصاحبه های ری اکت هم پرسیده میشه

لطفا برای مطالعه ادامه این مقاله + تیکه کد ها مثالهای بیشتر در وبسایت فِرانت اِندی روی لینک زیر کلیک کنید :

useReducer در ری اکت