مدیریت state برای مدیریت دادههای یک برنامه، نحوه تعامل کاربران با آن و نحوه رفتار بخشهای مختلف برنامه بسیار مهم است. مدیریت state چیزی نیست که فقط در React از آن استفاده کنیم، بلکه در ابزارهای محبوب دیگر مانند Angular.js، Vue.js و Next.js نیز مورد استفاده قرار میگیرد. دو راه متداول برای مدیریت state وجود دارد: ()useState و Redux. اما گزینههای دیگری مانند MobX، Zustand و Recoil نیز هستند.
در این مقاله قصد داریم تا با مدیریت state و چرایی اهمیت آن آشنا شویم. همچنین روشهای رایج مدیریت state را بررسی و نحوه عملکرد آنها را درک خواهیم کرد. پس از خواندن این مقاله، میتوانیم بهترین روش مدیریت state را برای برنامه خود انتخاب کنیم.
مدیریت state بخش مهمی از توسعه برنامه است. این کار به برنامه نویسان اجازه میدهد تا نحوه واکنش برنامه به رویدادهای مختلف و اقدامات کاربر را کنترل کنند. همچنین کمک میکند تا رابطهای کاربری پویا و تعاملی ایجاد کرده و تجربه کاربری بهتری داشته باشیم.
مدیریت state در بسیاری از وب سایتها و برنامهها، از ساده تا پیچیده، مورد استفاده قرار میگیرد. React و فریمورکهایی مانند Angular.js، Vue.js و Next.js اغلب از مدیریت state برای مدیریت دادهها و کنترل نحوه رفتار کامپوننتها استفاده میکنند.
برای درک بهتر مدیریت state، میخواهیم یک مثال عملی را باهم بررسی کنیم که نشان میدهد هوک ()useState و Redux چگونه در React کار میکنند.
ابتدا به پوشه پروژه میرویم. با استفاده از دستور create-react-appیا ابزار Vite یک React boilerplate ایجاد میکنیم. ما در این مقاله از vite استفاده میکنیم، زیرا برای توسعه سریعتر است و پیکربندی آسانی دارد. Vite همچنین کارایی بیشتری دارد و از دیگر فریم ورکهای فرانتاند مانند Svelte پشتیبانی میکند.
سپس در ادیتور دستور زیر را وارد میکنیم:
npx create-react-app ./ or npx create-vite@latest ./
./ React boilerplate را درست داخل پوشه یا دایرکتوری ایجاد شده برای ما میسازد.
()useState یک هوک داخلی در React است و state برنامههای React را به صورت local مدیریت میکند. هوک ()useState همچنین قابلیتهای مدیریت state را در فانکشنال کامپوننتها معرفی میکند. این بدان معناست که اکنون میتوانیم از منطق stateful در فانکشنال کامپوننتها استفاده کنیم.
در React، ما به هوکهای مختلف دیگری دسترسی داریم که میتوانیم آنها را import کرده و در برنامههای خود استفاده کنیم. این هوکها برنامه ما را پویاتر و کارآمدتر میکند.
میخواهیم برنامهای بسازیم که رنگ یک متن را بر اساس ورودی کاربر تغییر دهد. به عنوان مثال اگر inputای که کاربر وارد میکند red باشد، رنگ متن به قرمز تغییر پیدا کند.
استفاده از ()useState شامل یک فرآیند ساده است:
'react'import میکنیم.به عنوان مثال:
import React, { useState } from 'react';
const State = () => {
const [text, setText] = useState('black');
const [color, setColor] = useState('black'); // Another state to store the chosen color by the user
const handleInputChange = (e) => {
setText(e.target.value);
};
// A function is been declared
const handleButtonClick = () => {
setColor(text); // it updates the chosen color when the button is clicked
};
return (
<div>
<p style={{ color: color }}>
Progressively effective resources via business metrics.
</p>
<br />
<div className='inputBtn-container'>
<input
type='text'
className='input'
value={text}
onChange={handleInputChange}
/>
<button className='btn' onClick={handleButtonClick}>
Change text color
</button>
</div>
</div>
);
};
export default State;
در کد بالا، متغیر state با نام textبا استفاده از ()useState روی state اولیه (color) تنظیم شده است. تابع setTextنیز طوری تنظیم شده است که با کلیک روی دکمه، مقدار رنگ را بهروزرسانی میکند.
دومین state تعریف شده، ذخیره بهروزرسانی رنگی است که توسط کاربر وارد میشود. بنابراین رنگ text تا زمانی که بر روی دکمه کلیک نشود بدون تغییر باقی میماند. پس از کلیک روی دکمه، state رنگ با مقدار text بهروزرسانی میشود و رنگ text به آنچه کاربر تایپ میکند تغییر مینماید.
Redux یک کتابخانه جاوااسکریپت برای مدیریت stateها در برنامهها است که با React و سایر فریمورکها کار میکند. این کتابخانه به ما کمک میکند تا global state برنامه خود را مدیریت کنیم. علاوه بر این، عملکرد برنامه را نیز بهبود میبخشد.
همچنین میتوانیم Redux را به عنوان یک کنترل کننده ترافیک برای دادههای برنامه در نظر بگیریم. زیرا این اطمینان را ایجاد میکند که اطلاعات مناسب به بخشهای مناسب میروند، بنابراین همه چیز به آرامی اجرا میشود.
Redux ممکن است در ابتدا پیچیده به نظر برسد، اما چندین مزیت دارد که یادگیری آن را ارزشمند میکند:
ابتدا باید پکیج Redux را نصب کنیم:
npm install redux react-redux @reduxjs/toolkit
ما برای این کار سه دستور را باهم وارد کردیم که میتوانستیم هر یک را به شکل جداگانه نیز نصب کنیم. در ادامه هر دستور را به صورت جداگانه بررسی میکنیم که چه کاری را انجام میدهد.
npm install reduxکتابخانه Reduxرا نصب میکند.react-reduxبه این معنی است که Redux در یک برنامه React استفاده میشود. یعنی یکپارچگی را فراهم میکند.@reduxjs/toolkitابزارهایی را ارائه میدهد که کار با Redux را برای توسعهدهندگان تازهکار سادهتر میکند.در مرحله بعد به فایل package.jsonمیرویم تا مطمئن شویم که Redux به dependencyهای ما اضافه شده باشد. این فایل شامل اطلاعات مهمی در مورد پکیجهای مورد استفاده در پروژه میباشد.
سپس {configureStore} را از @reduxjs/toolkitبه فایلmain.jsیا index.js import میکنیم.
کامپوننت اصلی برنامه خود را داخل تگ provider قرار میدهیم و storeرا به عنوان یک ویژگی (props) به provider میدهیم. این کار باعث میشود تا store در سراسر برنامه در دسترس باشد.
Store: یک container در برنامه مانند یک واحد storage است. ما reducer را در داخل store تعریف میکنیم.
Redux بر اساس اصول یک store متمرکز عمل میکند. به این ترتیب، کل state برنامه را در خود نگه میدارد. زمانی که هر کامپوننت نیاز به دسترسی به state یا نیاز به یک بهروزرسانی داشته باشد، با store تعامل میکند. سپس store دادهها را مدیریت کرده و تغییرات را در هر بخش برنامه منتشر مینماید.
Reducer: یک reducer آبجکتی است که دو ورودی دارد: state قبلی و یک action. به این ترتیب state به روز شده را بر اساس actionهای ارسال شده return میکند. reducer اکشنها را بررسی میکند و تصمیم میگیرد که چگونه state برنامه را بهروزرسانی کند.
reducerها در Redux نحوه واکنش برنامه به مقادیر وارد شده توسط کاربرها را کنترل میکنند. این انعطافپذیری باعث میشود که در صورت نیاز، نگهداری و تغییر کد آسان شود. ما میتوانیم از importهای store و provider برای بهروزرسانی برنامه خود استفاده کنیم.
میخواهیم برنامهای بسازیم که رنگ را بر اساس ورودی کاربر تغییر دهد و این بار از Redux برای مدیریت state استفاده کنیم. ابتدا پوشهای به نام componentsمیسازیم. داخل آن پوشه، فایلی به نامChangeColor.jsxایجاد میکنیم.
در دایرکتوری پروژه خود، یک پوشه با نام featuresایجاد میکنیم. داخل این پوشه، فایلی به نام Color.jsایجاد مینماییم تا منطق Redux را برای برنامه ما نگه دارد.
در مرحله بعد، میخواهیم به کاربران اجازه دهیم تا رنگ مورد نظر خود را وارد کنند. برای انجام این کار، هوک ()useState را به صورت زیر در فایل ChangeColor.jsximport میکنیم:
import { useState } from 'react'; // useState() hook
const ChangeColor = () => {
const [color, setColor] = useState('');
return (
<div>
<p>Progressively effective resources via business metrics.</p>
<br />
<div className='inputBtn-container'>
<input
type='text'
className='input'
/>
<button className='btn'>change color text</button>
</div>
</div>
);
};
export default ChangeColor;
فایل color.jsکه منطق Redux را برای برنامه تنظیم میکند، شامل کد زیر میباشد:
// Import necessary functions from Redux Toolkit
import { createSlice } from "@reduxjs/toolkit";// Creating a slice for functionality is essential.
// Define the initial state for the slice
const initialState = "black"
// Create a slice using the createSlice function
const themeSlice = createSlice({
name: 'theme', // Name of the slice
initialState: { value: initialState},// Initial state for the slice
reducers: {
changeColor: (state, action)=>{
state.value=action.payload // Update the color value based on the dispatched action
},
}
}
})
color.jscreateSliceتابعی از Redux Toolkit است که به توسعهدهندگان اجازه میدهد تا reducerها را به روشی واضح و سازمانیافته ایجاد کنند. تقسیم منطق و دسترسی به آن در سراسر برنامه را ساده میکند. با createSlice، تغییر مقادیر و درک کد آسانتر میشود.nameرشتهای است که نام slice را مشخص میکند. این نام به عنوان پیشوند رشتههای action type تولید شده، مورد استفاده قرار میگیرد.initialStateمقدار state اولیه برای slice را مشخص میکند.Reducersهمانطور که در بخش قبل به آن اشاره کردیم،آبجکتهایی هستند که دو ورودی دارند: state قبلی و یک action. به این ترتیب state بهروز شده را بر اساس actionهای ارسال شده return میکنند. با استفاده از reducerها، میتوانیم برنامه را به صورت ساختاریافته مدیریت و بهروزرسانی نماییم.stateبه دادههای ذخیره شده و مدیریت شده توسط برنامه اشاره دارد. State مقادیر فعلی متغیرها، ویژگیها یا فیلدهایی را که تعیین میکنند برنامه چگونه رفتار کند یا ظاهر آن چگونه باشد، نگهداری میکند.actionیک آبجکت جاوااسکریپتی ساده است که قصد تغییر state را توصیف میکند. به عبارت دیگر action نحوه ارتباط ما با reducerها برای شروع بهروزرسانیهای state است.پس از تعریف منطق reducer، میتوانیم آن را export کنیم و در هر جایی که نیاز به مدیریت state داریم آن را import کرده و مورد استفاده قرار دهیم. مثلا در فایل changeColor.jsx. فایل زیر، فایل export شده برای فایل changeColor.jsx میباشد:
import { createSlice } from "@reduxjs/toolkit";
const initialState="black"
export const themeSlice = createSlice({
name: 'theme',
initialState: { value: initialState},
reducers: {
changeColor: (state, action)=>{
state.value=action.payload
}
}
})
// Export the reducer function
export const { changeColor } = themeSlice.actions
export default themeSlice.reducer
changeColor.jsxuseSelectorرا از react-redux import میکنیم تا دادهها را از Redux store دریافت کنیم. این کار به ما کمک میکند تا مقدار رنگ فعلی را از state دریافت نماییم.useDispatchرا از react-reduximport میکنیم تا actionها را به Redux store ارسال کنیم. به این ترتیب میتوانیم مقدار رنگ را در state بهروزرسانی کنیم.Color.jsرا که حاوی منطق Redux و شامل reducer و action تغییر رنگ است، import میکنیم.به این ترتیب:
useSelectorاز Redux store دریافت میکنیم.با این تغییرات، کامپوننت ChangeColorاکنون از Redux برای مدیریت state استفاده میکند. کاربران میتوانند با تایپ رنگ دلخواه خود در قسمت input و کلیک بر روی دکمه «تغییر رنگ متن» رنگ متن نمایش داده شده را تغییر دهند.
اکنون کد کامل مدیریت state به شکل زیر میباشد:
import { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { changeColor } from '../features/Color';
const ChangeColor = () => {
// State to hold the selected color
const [color, setColor] = useState('');
// Accessing the dispatch function from react-redux
const dispatch = useDispatch();
// Accessing the theme color value from the Redux store
const themeColor = useSelector((state) => state.theme.value);
// Event handler for the input change
const handleColorChange = (e) => {
setColor(e.target.value);
};
// Event handler for the button click
const handleButtonClick = () => {
// Dispatching the changeColor action with the selected color
dispatch(changeColor(color));
};
return (
<div style={{ color: themeColor }}>
<p>Progressively effective resources via business metrics.</p>
<br />
<div className='inputBtn-container'>
<input type='text' className='input' onChange={handleColorChange} />
<button className='btn' onClick={handleButtonClick}>
Change text color
</button>
</div>
</div>
);
};
export default ChangeColor;
این مقاله دو راه حل برای مدیریت state را پوشش می دهد: هوک ()useState برای برنامههای کوچک تا متوسط و Redux برای برنامههای بزرگتر است. برای انتخاب بهترین روش باید مواردی مانند پیچیدگی برنامه، اندازه تیم و نیازهای عملکردی را در نظر بگیریم. همچنین داشتن درک درست از نحوه کارکرد هر دو رویکرد به ما در انتخاب درستتر کمک میکند.