آموزش Redux - مقدمه ای بر State Management در React

Redux یک state container برای JavaScript است و به عنوان یک کتابخانه خارجی که می تواند همراه با فریمورک های front-end مانند React ،Angular ، Ember.js ، Backbone و غیره استفاده شود، می آید. با این حال Redux اغلب با React استفاده می شود.

مشکل معماری سنتی MVC

قبل از اینکه بیشتر به مفاهیم Redux بپردازیم، ابتدا بر روی مشکلاتی که حل می کند تمرکز کنیم. الگوی Model-View-Controller (MVC) امروزه برای اکثر توسعه دهندگان front-end وب آشنا است. این الگو تفکیک بین داده ها (مدل)، ارائه (نمایش) و منطق برنامه (کنترل کننده) را توصیف می کند و تضمین می کند که برنامه شما به روشی ساخت یافته ساخته شده است و شما نگرانی ها و مشکلات را از یکدیگر تفکیک کرده اید..

اما عیبش این است که شما کنترل جریان داده خود را از دست می دهید. به طور کلی جریان داده ها دو جهته است. ورودی کاربر در یک کامپوننت می تواند بر سایر کامپوننت ها تأثیر بگذارد و بالعکس. کنترل جریان داده ها و اطمینان از به روزرسانی کلیه کامپوننت های رابط کاربری بر این اساس، یک کار مستعد خطا است.

مدیریت state چگونه مسئله را حل می کند

با استفاده از Redux در حال حل این مشکلات با معرفی یک data store مرکزی در برنامه خود هستیم. store شامل state برنامه است و source of truth برای کامپوننت های برنامه است. با استفاده از کانسپت store نیازی به همگام سازی state بین کامپوننت ها نیست. در عوض می توانید در هر زمان کاملا به store خود Redux اعتماد کنید.

بلوک های سازنده Redux

برای درک کامل مفهوم Redux، ابتدا باید نگاهی به بلوک سازنده بیندازیم. Redux دارای سه قسمت اصلی است: Actions ،Reducers و Store. بیایید بررسی کنیم که هرکدام چه کاری انجام می دهد:

Actions

Actions برای ارسال اطلاعات از برنامه به store استفاده می شود. ارسال اطلاعات به store برای تغییر state برنامه پس از تعامل کاربر، رویدادهای داخلی یا تماسهای API لازم است.

Actions اشیای جاوا اسکریپت هستند، همانطور که در مثال زیر مشاهده می کنید:

{
    type: LOGIN_USER,
    payload: {username: ‘sebastian’, password: ‘123456’}
}

در اینجا شی action دارای دو ویژگی است:

  • type: یک ثابت برای شناسایی نوع action
  • payload: شی object اختصاص داده شده به این ویژگی حاوی داده هایی است که به store ارسال می شود

اشیا Action با استفاده از توابع ایجاد می شوند. این توابع را action creators می نامند:

function authUser(data) {
    return {
        type: LOGIN_USER,
        payload: data
    }
}

در اینجا می بینید که تنها هدف تابع action creator، بازگرداندن شی action همانطور که شرح داده شده است.

call کردن action ها در برنامه با استفاده از تابع dispatch آسان است:

dispatch(authUser(data));

Reducers

Reducers مهمترین عنصر سازنده هستند و برای درک مفهوم، مهم هستند. Reducers توابع pure جاوا اسکریپت هستند که state فعلی برنامه و یک شی action را می گیرند و state جدید برنامه را برمی گردانند:

function myReducer (state , action)  {
  switch (action.type) {
    case ' LOGIN_USER':
        return Object.assign({}, state, {
        auth: action.payload
        })
        default:
        return state
        }
        }

نکته مهمی که باید در اینجا مورد توجه قرار گیرد این است که مستقیماً state تغییر نمی کند. در عوض یک شی جدید state (بر اساس state قدیمی) ایجاد می شود و به روزرسانی برای state جدید انجام می شود.

Store

store اشیا مرکزی است که state برنامه را حفظ می کند. store با استفاده از روش createStore از کتابخانه Redux ایجاد می شود:

import { createStore } from ‘redux’;
let store = createStore(myReducer);

شما باید تابع reducer را به عنوان یک پارامتر pass بدهید. اکنون شما آماده هستید تا یک action را به store اختصاص (disptach) دهید که توسط reducer اداره می شود:

let authData = {username: ‘sebastian’, password: ‘123456’};
store.dispatch(authUser(authData));

شکل زیر جریان داده بین بلوک های سازنده را نشان می دهد:

ساخت نمونه ای از برنامه React-Redux

آنچه ما قصد ساخت آن را داریم

حال بیایید با قسمت عملی این آموزش، ادامه دهیم و از ابتدا ساخت یک برنامه کاربردی React-Redux در دنیای واقعی را شروع کنیم. در تصویر زیر می توانید آنچه را که می خواهیم بسازیم مشاهده کنید:

این برنامه به کاربر این گزینه را می دهد تا با کلیک روی لوگو ها به فریمورک front-end مورد علاقه خود رای دهد. تعداد آرا در store برنامه ذخیره می شود و هر زمان که کاربر رأی می دهد، به روز می شود.

نتیجه رأی گیری در زیر توسط یک کامپوننت جداگانه React نشان داده می شود. این component برای گرفتن مقادیر رای گیری فعلی برای هر فریمورک به store دسترسی پیدا می کند.

راه اندازی پروژه React

ابتدا باید یک پروژه جدید React راه اندازی کنیم. ساده ترین راه برای انجام این کار استفاده از create-react-app است:

$ create-react-app my-redux-app

وارد دایرکتوری ایجاد شده my-redux-app شوید و وب سرور development را start کنید:

$ cd my-redux-app

$ yarn start

در آخر باید مطمئن شویم که Redux به پروژه ما اضافه شده است:

$ yarn add redux

پیاده سازی Actions

بیایید با ایجاد یک فایل index.js جدید در دایرکتوری src/actions، پیاده سازی را شروع کنیم. این فایل شامل توابع action creator است که در برنامه ما مورد نیاز است:

export const voteAngular = () => {
  return {
    type: 'VOTE_ANGULAR'
  }
}

export const voteReact = () => {
  return {
    type: 'VOTE_REACT'
  }
}

export const voteVuejs = () => {
  return {
    type: 'VOTE_VUEJS'
  }
}

کاربر می تواند از لیست سه فریم ورک front-end انتخاب کند:
Angular، React، Vue.js.
ما در اینجا سه action creators مربوطه را تعریف می کنیم. شی action که در هر سه حالت ایجاد می شود فقط شامل ویژگی type با یکی از انواع زیر است:

  • VOTE_ANGULAR
  • VOTE_REACT
  • VOTE_VUEJS

در این حالت استفاده از یک شی payload ضروری نیست زیرا نیازی به انتقال داده به store نداریم. ما فقط به اطلاعاتی که یک کاربر رای داده است، برای افزایش شمارنده رای در store نیاز داریم.

پیاده سازی Reducers

در مرحله بعدی، بیایید تابع Reducer را پیاده سازی کنیم. یک فولدر جدید src/reducers ایجاد کنید و در داخل آن فولدر، فایل index.js را ایجاد کنید و کد زیر را وارد کنید:

ابتدا ما یک شی const تعریف می کنیم که حاوی state اولیه برنامه ما است. شی state از سه ویژگی angular، react و vuejs تشکیل شده است. در ابتدا مقادیر این خصوصیات روی 0 تنظیم می شوند.

برای ست کردن state اولیه، باید شی initialState را به اولین پارامتر state تابع reducer به عنوان مقدار پیش فرض اختصاص دهیم.

تابع Reducer شامل یک عبارت سوئیچ است که سه مورد را کنترل می کند:

  • VOTE_ANGULAR:اگر عملی از نوع VOTE_ANGULAR به store ارسال شده باشد، یک آبجکت state جدید ایجاد می شود و مقدار state مربوط به ویژگی angular افزوده می شود.
  • VOTE_REACT: اگر عملی از نوع VOTE_REACT به store ارسال شده باشد، یک آبجکت state جدید ایجاد می شود و مقدار state مربوط به ویژگی react افزوده می شود.
  • VOTE_VUEJS: اگر عملی از نوع VOTE_VUEJS به store ارسال شده باشد، یک آبجکت state جدید ایجاد می شود و مقدار state مربوط به ویژگی vuejs افزوده می شود.

در هر حالت از روش Object.assign برای ایجاد یک آبجکت جدید state استفاده می شود.

ایجاد Store

برای تکمیل قسمت های Redux برنامه های خود، اجازه دهید store را در فایل index.js ایجاد کنیم:

ابتدا اطمینان حاصل می کنیم که createStore را import کرده باشیم. علاوه بر این، ما Reducer را هم import می کنیم. سپس store با فراخوانی createStore و عبور از Reducer به عنوان یک پارامتر ایجاد می شود.

در آخر ما باید store.subscribe(render) را فراخوانی کنیم. این کار باعث می شود که از فراخوانی تابع render هر زمان که وضعیت برنامه تغییر می کند، اطمینان حاصل کنیم.

پیاده سازی کامپوننت App

اکنون که بلاک اصلی Redux را در برنامه خود پیاده سازی کرده ایم، باید کامپوننت های React مورد نیاز را نیز پیاده سازی کنیم. ما با تغییر در پیاده سازی اولیه ی کامپوننت App به شکل زیر شروع می کنیم:

همانطور که مشاهده می کنید ما از برخی کلاس های Bootstrap CSS در کد JSX استفاده می کنیم. jumbotron به عنوان عنصر اصلی که شامل header و لوگو ها است، استفاده می شود. برای هر لوگو ما از ویژگی onClick استفاده می کنیم تا تابع event handler را به event کلیک image متصل کنیم.

سه تابع  event handler یعنی handleVoteAngular ،handleVoteReact و handleVoteVuejs نیز پیاده سازی شده اند. تنها وظیفه ای که باید در توابع event handler انجام شود، ارسال action مربوطه به store است. برای دسترسی به store برنامه، شی store به عنوان یک property به کامپوننت منتقل می شود:

پیاده سازی کامپوننت Results

نمایش نتایج رای گیری توسط یک کامپوننت دیگر انجام می شود: Results. بیایید فایل جدید results.js در دایرکتوری src/components را ایجاد کنیم. source code را می توان در لیست زیر مشاهده کرد:

باز هم، store به عنوان یک property به کامپوننت منتقل می شود. از constructor برای ایجاد store از طریق this.store استفاده می شود.

برای نمایش نتایج رأی گیری به صورت درصدی، سه تابع کمکی تعریف شده است: votesAngularInPercent، votesReactInPercent و votesVuejsInPercent.

سه تابع کمکی اضافی (votesAngularInPercentStyle، votesReactInPercentStyle و votesVuejsInPercentStyle) برای بازگرداندن مقدار عرض CSS برای نتیجه رای گیری فعلی تعریف شده است که در کد JSX برای تنظیم مقدار style عنصر progress bar استفاده می شود.

برای اینکه خروجی کامپوننت Results در خروجی اپلیکیشن قابل مشاهده باشد، تغییرات زیر را در index.js اعمال می کنیم:

ابتدا عبارت import برای Results اضافه می شود و دوم، عنصر <‌Results store={store}/‌> به کد JSX درون تابع render اضافه می شود.

با انجام این تغییرات، باید نتیجه نهایی برنامه رأی گیری ما را در مرورگر خود مشاهده کنید.

نتیجه

اگر کار خود را با Redux آغاز کنید ممکن است این تصور را داشته باشید که کد بیشتری لازم است و پیچیدگی برنامه شما در حال افزایش است. این ممکن است در ابتدا درست باشد اما Redux وقتی برنامه شما بزرگتر شود و از کامپوننت های زیادی تشکیل شود، قدرت خود را نشان می دهد.

Redux به شما کمک می کند تا یک ساختار ثابت و واضح در پروژه خود داشته باشید، از جریان داده واضح اطمینان می یابد و از همگام ماندن کامپوننت ها اطمینان حاصل می کند.

سعید نصیری
سعید نصیری

من برنامه نویس لاراول، PHP و طراح سایت هستم. برنامه نویسی موبایل و تولید اپلیکیشن های موبایل نیز بخش دیگری از توانایی های فردی من هست. تقریبا ده دوازده سالی تجربه مستمر در زمینه طراحی سایت دارم و نزدیک به یک سال هم میشه که در برنامه نویسی موبایل وارد شده ام.

× در حال پاسخ به: