در این مقاله مفهوم redux و کلیت Redux-toolkit را مورد بررسی قرار میدهیم تا مفهوم کلی این موارد را متوجه شده و بتوانیم پروژه های ساده ای با آن پیاده سازی نماییم. در نظر داشته باشید استفاده از ریداکس اجباری نیست و بیشتر برای پروژه های با مقیاس بزرگ توصیه میشود .
Redux یک کتابخانه جاواسکریپت است که برای ساخت رابط کاربری اپلیکیشنها و صفحات وب استفاده میشود. این کتابخانه حالات (states) مختلف را در برنامههای جاوا اسکریپت مدیریت میکند.
ما برای استفاده از دیتا در کامپوننت ها از props استفاده میکنیم تا بتوانیم دیتا را به کامپوننت ها پاس بدهیم.
اما وقتی تعداد کامپوننت های تو در تو زیاد بشود، استفاده از این روش اصلا پیشنهاد نمیشه و به این شلوغ کاری به اصطلاح prop drilling گفته میشه.
به زبان ساده تر ، انتقال، اشتراک گزاری و تغییر داده در تمامی کامپوننت ها باعث شلوغی و بهم ریختگی می شود.Redux اینکار را با جداسازی لایه data از بقیه کدها آسانتر میکند.
ریداکس که در سال 2015 عرضه شده است. یک کتابخانه برای مدیریت کردن استیت های گلوبال هستش که در کتابخانه و فریمورک هایی مثل ری اکت و انگولار از آن استفاده میشود.
البته اگر پروژه بزرگ و پیچیده باشد مناسبتراست، در غیر اینصورت مواردی مانند context api کفایت میکند.
این کتابخانه با تمام وابستگیهای خود (Dependency) تنها 2 کیلوبایت حجم دارد و با بکارگیری آن، لازم نیست نگران سنگین شدن پروژه خود باشید.
قبل از آن که در کدنویسی ریداکس ریز شویم، اجازه دهید مفهومی به نام فلاکس را بررسی کنیم.
آیا میدانید مدرسه پرنیان، دوره طراحی سایت حرفه ای بصورت حضوری و مجازی برگزار میکند؟
Actions − اکشن ها به dispatcher ارسال می شوند تا جریان داده آغاز شود .
Dispatcher − این قسمت مغر اصلی توزیع داده است و داده را به Store منتقل میکند .
Store − استور جایی ست که استیت ها و منطق برنامه قرار دارد. هر استور یک استیت دارد که بر اساس نیاز قابل تغییر است .
View − این بخش اطلاعات را از Store دریافت می کند و بر روی صفحه چاپ می کند.
Redux برای ذخیره دادهها در لایه نمایش مورد استفاده قرار میگیرد. کاربرد اصلی ریداکس در کنار فریم ورک هایی مانند React و React Native است.
اما میتوان از آن در Angular، Angular2، Vue، Mithril و سایر کتابخانههای JS استفاده کرد چون ریداکس هیچ مشکلی در ادغام شدن با سایر فریم ورکها ندارد. این فریم ورک با یک مکانیسم ساده به راحتی خودش را در کنار سایر زبانها جا میدهد.
جایی هست که تمامی داده ها نگه داری می شود.store یک اتصال راحت برای تعامل با state های global در اپلیکیشن فراهم می کند.
کارهایی که قرار است ما با Store انجام بدیم.هر زمانی که ما میخوایم قسمتی از state را تغییر بدهیم، این فرآیند با یک Action انجام میشه.اکشن فقط یک JSON objects است.
زمانی که ما بخواهیم یک action اجر شود، ما action رو dispatch می کنیم.
قاعدتا از اینجا به بعد این مقاله مفهوم redux و کلیت Redux-toolkit ، انتظار کدنویسی در بستر ریداکس و آموزش آن را میکشید. اما باید به شما بگوییم که ریداکس سختی هایی به همراه دارد و شاید به مقدار این حجم کار، خروجی مناسبی به ما نمیدهد!
در ریداکس ما مجبوریم پکیجایی مثل redux-thunk, redux-persist , redux-saga و… نصب کنیم و همین امر باعث شلوغی بیش از حد کد میشود و مشکلات فراوانی به همراه خواهد داشت. در ضمن کانفیگ کردن آن هم میتواند سخت باشد.
خب… راه حل پس چیست؟
redux-toolkit آمده که همه ی این کارها را یکجا به ما بدهد و کار را راحت تر کند.
برای حل این مشکل، یکی از maintainerهای اصلی تیم ریداکس، یک پروژه را تحت عنوان Redux Toolkit، مدتها قبل برای حل مشکلات عنوان شده شروع کرده است و این پکیج، جدیداً به قالب رسمی create-react-app اضافه شده است.
که در واقع یک روش استاندارد و به اصطلاح opinionated برای ایجاد پروژههای ریداکسی میباشد و شامل تمامی وابستگیهای موردنیاز برای کار با Redux از قبیل redux-thunk و همچنین Redux DevTools است.
پس بهتر است به این نکته دقت کنید که redux-toolkit در واقع یه راه برای ساده تر نوشتن ریداکس میباشد و در پشت پرده دقیقا همون کارایی که با ریداکس میکردیم را انجام میدهد. منتها ما دیگر نیازی نیست با خیلی از این پیچیدگی هایی که ریداکس داشت سر و کله داشته باشیم.
در ابتدا در CMD کامند زیر را بزنید تا با تمام پکیج های redux-thunk , rtk query و… نصب شود.
npx create-react-app myRedu –template redux
cd myRedu
npm start
این ساختار خیلی شبیه به قالب پیشفرض create-react-app میباشد. مهم است در ابتدای آموزش ساختار فایل ها و کدهای دیفالت ریداکس تولکیت را کامل بشناسیم. به همین منظور یک مرور کلی بروی مهمترین موارد این فایل ها خواهیم داشت.
پروژهی ایجاد شدهی با قالب redux ، یک فایل با نام store و همچنین یک دایرکتوری را به نام features دارد. اگر به فایل store.js مراجعه کنید، خواهید دید که تنظیمات اولیهی ایجاد store را در قالب یک مثال Counter ایجاد کردهاست:
در کد فوق، نحوهی ایجاد store، نسبت به حالت معمول ریداکس ، آسان تر و خواناتر است. نکتهی جالب این است که به همراه کد فوق، Redux DevTools و همچنین redux-thunk هم از قبل تنظیم شدهاند و در نتیجه، نیازی به تنظیم و نصب آنها نیست.
reducer در ریداکس یک تابع جاوا اسکریپتی است، این تابع دو پارامتر میگیرد: state فعلی و action.
ویژگی مهم دیگر در تولکیت ، پوشهی features میباشد که یک روش رایج برای گروهبندی کامپوننتها، همراه با فایلهای وابستهی آنها است.
فایل های درون پوشهی features عبارتست از:
Counter
Counter.module.css
counterSlice.js
counterAPI
counterSlice.spec
در بین اینها، مهمترین فایل counter.js است که در نهایت درون صفحه رندر خواهد شد.
درون این فایل با استفاده از Redux Hooks کار اتصال به store و همچنین dispatch کردن اکشنها صورت میپذیرد.
کد صفحه counter.js را باز کنید. همانطور که میبینید، تعدادی button در خروجی کامپوننت اصلی صفحه قرار گرفته اند که با کلیک بروی هر کدام ، dispatch مربوطه از صفحه counterSlice فراخوانی میشود.
البته قبل از آن تمام این dispatch ها از counterSlice در صفحه counter فراخوانی شده اند.
در نظر داشته باشید، مقدار استیت اصلی در counter.js است.
const [incrementAmount, setIncrementAmount] = useState(‘2’);
اما با توجه به اکشن های روی باتن های داخل صفحه، آپدیت مقدار با توجه به اکشن مربوطه در صفحه counterSlice انجام میپذیرد. در این قالب جدید، ترکیب این قطعات هستند که شیء اصلی یا در واقع همان state کلی پروژه را تشکیل خواهند داد.
برای ایجاد یک قطعه جدید، از تابع createSlice استفاده شده است. این تابع، تعدادی پارامتر را از ورودی دریافت میکند:
در نهایت خروجی صفحه counterSlice به صفحه store در پوشه store منتقل میشود.
import counterReducer from ‘../features/counter/counterSlice’;
در نظر داشته باشید در نهایت خروجی counter.js در صفحه رندر خواهد شد و در APP.js فراخوانی میشود.
import { Counter } from ‘./features/counter/Counter’;
قطعا در جریان هستید که فایل Counter.module.css در واقع استایلهای مربوط به کامپوننت فوق میباشد که به صورت CSS module اضافه شدهاست.
تعریف من از ریداکس : Redux is a global state
و اما در ادامه برای درک بهتر مفهوم ریداکس تولکیت…
من در این آموزش روی رابط کاربری تمرکز نمی کنم و بیشتر تمرکز بروی کدها میباشد.
حالا ما رابط کاربری داریم که به شکل زیر است:
برای شروع از صفحه index.js کد زیر را درج میکنیم.
همانطور که در کد بالا میبینید، مقدار Provider را از react-redux فراخوانی کرده و همچنین مقدار STORE را از پوشه خود فراخوانی میکنیم. در نهایت در ReactDOM.render به Provider ارزش یا مقدار استور را میدهیم.
بهتر است همین الان تکلیف کدهای استور را نیز معلوم کنیم. کد زیر را در استور خود قرار دهید:
STORE مؤلفهای است که شما به ارائهدهنده redux ارائه میدهید که آن را از وجود وضعیت آگاه میکند.
این کد باعث می شود استور به reducer ما گوش دهد و به این ترتیب می توانیم به متغیرها و توابع داخل دسترسی پیدا کنیم. ما reducer خود را “todo” نامگذاری می کنیم.
اما بعد از این دو فایل، یکی از فایل های اصلی ما App.js میباشد. کد زیر را در آن وارد کنید:
No todos
}همانطور که در خط اول میبینید، useSelector و useDispatch برای استفاده از state که به تازگی در برنامه ایجاد شده است، ایمپورت میکنیم.
در تابع App، با استفاده از useSelector، هر دو استیت count و todo را دریافت کنید.(هر دو در فایل todoslice وجود دارند که در ادامه آن را خوهیم ساخت)
توجه داشته باشید که برای دسترسی به هر یک از این حالت ها، باید به نام reducer که در فایل store مشخص شده است دسترسی داشته باشید.
تابع dispatch را که برای اجرای توابع addTodo و removeTodo استفاده می شود، استخراج کنید.
تابع handleAddTodo را بنویسید که هنگام ارسال فرم فعال می شود.
فراخوانی ()e.preventDefault ضروری است زیرا اقدام پیشفرض فرم این است که صفحه را پس از ارسال بهروزرسانی کند. اگر به آن اجازه دهید صفحه را رفرش کند، تمام وضعیت ما بازنشانی و صفر می شود.
برای تابع handleTodoDone، زمانی که کاربر روی یک مورد todo کلیک میکند، آن را فعال میکند. شناسه todo برای تشخیص اینکه کدام todo حذف شده است استفاده می شود.
ادامه کد هم که واضح است. در خروجی HTML از آرایه todos که در صفحه todoslice(ساخته خواهد شد) ایجاد و پر میشود، یک حلقه زده و مقادیر داخل آن را پر میکند و نشان میدهد. در صورت نداشتن مقدار، متن no todo منتشر میشود.
یک فایل TodoItem.js بسازید و کد زیر را در آن منتشر کنید:
todoitem همان فایلی است که در App.js مستقیم فراخوانی کردیم و در قسمت return تابع اصلی آن، بر طبق ساختار اصلی آن، حلقه MAP زدیم و خروجیمان را تشکیل دادیم.
این فایل میگوید که به ازای هر مرتبه حلقه MAP یک دیویژن که در خود یک input و label دارد ایجاد کن و به event آن، مقدار deleteTodo را منتسب کن.
deleteTodo قرار است کل دیویژن را حذف نماید.
آخرین فایلمان، ToDoSlice.js است. آن را ایجاد کرده و مقدار کد زیر را در آن درج نمایید:
برای ساختن اسلایس، باید createSlice را وارد کنید. که تابعی در داخل بسته Redux Toolkit است.
بعد، استیت اولیه خود را تعریف کنید. در این حالت، دو متغیر بخشی از استیت خواهند بود:
count: یک عدد صحیح که تعداد کارهای موجود در برنامه را ردیابی می کند (در ابتدا برابر با 0)
todos: لیستی که شامل تمام کارهایی است که کاربر اضافه کرده است (در ابتدا خالی)
اکنون از تابع createSlice که وارد شده است استفاده کنید. سه آرگومان ورودی می گیرد:
نام اسلایس (در این مورد todo)
استیت اولیه (تعریف شده در بالا)
reducer (توابعی که برای تغییر مقادیر state استفاده خواهند شد)
اما در ادامه…
addTodo ← با استفاده از متن ارسال شده در آرگومان یک آیتم todo جدید ایجاد می کند و یک شناسه تصادفی به آن اختصاص می دهد. این todo ایجاد شده را به لیست todos ، پوش (PUSH) میکند و مقدار شمارش را افزایش می دهد.
توجه داشته باشید که برای دریافت آرگومان به تابع، از action.payload استفاده می کنیم. اگر به بیش از یک آرگومان نیاز دارید، می توانید آرگومان ها را به عنوان یک شی ارسال کنید و با استفاده از payload به آن دسترسی داشته باشید.(action.payload.variable)
removeTodo ← مورد todo را با استفاده از شناسه داده شده در آرگومان ها از لیست کارها حذف می کند و مقدار شمارش را کاهش می دهد.
فراموش نکنید در نهایت، reducer را صادر کنید. این در STORE استفاده می شود تا بتوان state را به برنامه provide کرد.
امیدواریم از این مقاله نهایت استفاده را برده باشید و آن را با دوستانتان به اشتراک بگذارید. تیم تولید محتوای مدرسه اینترنتی پرنیان این مقاله را تهیه کرده است.