نحوه استفاده از Redux در برنامه React TypeScript

ترجمه و تالیف : عرفان حشمتی
تاریخ انتشار : 29 آبان 99
خواندن در 3 دقیقه
دسته بندی ها : react

Redux یک کانتینر قابل پیش‌بینی برای برنامه‌های جاوااسکریپت است. این یک کتابخانه محبوب برای مدیریت state در برنامه‌های React است.

هنگام استفاده از آن به همراه TypeScript می‌تواند تجربه بهتری از توسعه نرم‌افزار را ارائه دهد. تایپ اسکریپت یک مجموعه برتر از جاوااسکریپت است که برای قوی و قابل درک بودن کد آن را تایپ می‌کند.

در این مقاله، با ساخت برنامه‌ای که به شما امکان افزودن، حذف و نمایش را می‌دهد، نحوه استفاده از Redux در پروژه React TypeScript را به شما نشان می‌دهیم.

بیایید شروع کنیم.

  • پیش نیازها
  • تنظیمات اولیه
  • ایجاد type ها
  • ایجاد action type ها
  • ایجاد action creator ها
  • ایجاد reducer
  • ایجاد store
  • ایجاد کامپوننت‌ها

پیش نیازها

این آموزش فرض می‌کند که شما حداقل یک درک اساسی از React ، Redux و TypeScript دارید.

بنابراین اگر با این فن‌آوری‌ها آشنایی ندارید، ابتدا سعی کنید این راهنمای کاربردی TypeScript یا این آموزش React Redux را بخوانید. در غیر این صورت، بیایید استارت کار را بزنیم.

تنظیمات اولیه پروژه

برای استفاده از Redux و TypeScript، باید یک برنامه جدید React ایجاد کنیم.

برای انجام این کار، بیایید CLI (رابط خط فرمان) را باز کرده و این دستور را تایپ کنیم:

  npx create-react-app my-app --template typescript

سپس بیایید پروژه را به صورت زیر ساختار دهیم:

├── src
|  ├── components
|  |  ├── AddArticle.tsx
|  |  └── Article.tsx
|  ├── store
|  |  ├── actionCreators.ts
|  |  ├── actionTypes.ts
|  |  └── reducer.ts
|  ├── type.d.ts
|  ├── App.test.tsx
|  ├── App.tsx
|  ├── index.css
|  ├── index.tsx
|  ├── react-app-env.d.ts
|  └── setupTests.ts
├── tsconfig.json
├── package.json
└── yarn.lock

ساختار فایل پروژه کاملاً ساده است. با این وجود، باید دو مورد را در نظر گرفت:

  • پوشه store که شامل فایل‌های مربوط به React Redux است.
  • فایل type.d.ts که انواع TypeScript را در خود نگه می‌دارد و می‌تواند بدون وارد کردن در فایل‌های دیگر مورد استفاده قرار گیرد.

همانطور که گفته شد، اکنون می‌توانیم Redux را نصب کرده و اولین store خود را ایجاد کنیم.

بنابراین بیایید پروژه را باز کرده و دستور زیر را اجرا کنیم:

  yarn add redux react-redux redux-thunk

یا هنگام استفاده از npm:

  npm install redux react-redux redux-thunk

ما همچنین باید انواع آن‌ها را به عنوان وابستگی توسعه نصب کنیم تا به TypeScript در درک کتابخانه‌ها کمک کنیم.

بنابراین بیایید این دستور را دوباره روی CLI اجرا کنیم.

 yarn add -D @types/redux @types/react-redux @types/redux-thunk

یا برای npm:

  npm install -D @types/redux @types/react-redux @types/redux-thunk

اکنون می‌توانیم انواع TypeScript را برای پروژه در بخش بعدی ایجاد کنیم.

ایجاد type ها

تایپ‌های TypeScript به شما امکان می‌دهد انواع را برای متغیرها، پارامترهای توابع و ... تعیین کنید.

interface IArticle {
  id: number
  title: string
  body: string
}

type ArticleState = {
  articles: IArticle[]
}

type ArticleAction = {
  type: string
  article: IArticle
}

type DispatchType = (args: ArticleAction) => ArticleAction

در اینجا ما با اعلام رابط IArticle شروع می‌کنیم که شکل خاصی را منعکس می‌کند.

سپس ArticleState ، ArticleAction و DispatchType را داریم که به عنوان نوع، به ترتیب برای شی state، action creator ها و تابع dispatch ارائه شده توسط Redux عمل می‌کنند.

ما اکنون انواع لازم را برای شروع استفاده از React Redux داریم. بیایید انواع action را ایجاد کنیم.

ایجاد action type ها

store/actionTypes.ts

export const ADD_ARTICLE = "ADD_ARTICLE"
export const REMOVE_ARTICLE = "REMOVE_ARTICLE"
 

برای استور Redux به دو نوع اکشن نیاز داریم. یکی برای افزودن و دیگری برای حذف.

ایجاد action creator ها

store/actionCreators.ts

import * as actionTypes from "./actionTypes"

export function addArticle(article: IArticle) {
  const action: ArticleAction = {
    type: actionTypes.ADD_ARTICLE,
    article,
  }

  return simulateHttpRequest(action)
}

export function removeArticle(article: IArticle) {
  const action: ArticleAction = {
    type: actionTypes.REMOVE_ARTICLE,
    article,
  }
  return simulateHttpRequest(action)
}

export function simulateHttpRequest(action: ArticleAction) {
  return (dispatch: DispatchType) => {
    setTimeout(() => {
      dispatch(action)
    }, 500)
  }
}

در این آموزش، درخواست HTTP را با تاخیر 0.5 ثانیه‌ای شبیه سازی می‌کنیم. اگر می‌خواهید از یک سرور واقعی استفاده کنید.

در اینجا تابع addArticle اکشنی را برای افزودن شی جدید ارسال می‌کند و متد removeArticle برعکس آن عمل می‌کند. بنابراین شی passed منتقل شده را به عنوان آرگومان حذف کنید.

ایجاد یک reducer

reducer یک تابع خالص است که state استور و یک action را به عنوان پارامتر دریافت می‌کند و سپس state به روز شده را برمی‌گرداند.

store/reducer.ts

import * as actionTypes from "./actionTypes"

const initialState: ArticleState = {
  articles: [
    {
      id: 1,
      title: "post 1",
      body:
        "Quisque cursus, metus vitae pharetra Nam libero tempore, cum soluta nobis est eligendi",
    },
    {
      id: 2,
      title: "post 2",
      body:
        "Harum quidem rerum facilis est et expedita distinctio quas molestias excepturi sint",
    },
  ],
}

همانطور که در اینجا مشاهده می‌کنید، ما یک state اولیه را تعریف می‌کنیم که برخی از اشیا را برای بارگذاری صفحه نشان دهیم. هدف state باید با نوع ArticleState مطابقت داشته باشد، در غیر این صورت TypeScript خطایی ایجاد می‌کند.

store/reducer.ts

const reducer = (
  state: ArticleState = initialState,
  action: ArticleAction
): ArticleState => {
  switch (action.type) {
    case actionTypes.ADD_ARTICLE:
      const newArticle: IArticle = {
        id: Math.random(), // not really unique
        title: action.article.title,
        body: action.article.body,
      }
      return {
        ...state,
        articles: state.articles.concat(newArticle),
      }
    case actionTypes.REMOVE_ARTICLE:
      const updatedArticles: IArticle[] = state.articles.filter(
        article => article.id !== action.article.id
      )
      return {
        ...state,
        articles: updatedArticles,
      }
  }
  return state
}

export default reducer

سپس تابع reducer را داریم که انتظار می‌رود state قبلی و action بتوانند store را به روز کنند. در اینجا ما دو اکشن داریم: یکی برای اضافه کردن و دیگری برای حذف.

با قرارگیری این وضعیت، اکنون می‌توانیم state را با reducer کنترل کنیم. حالا بیایید یک store برای پروژه ایجاد کنیم.

ایجاد یک store

استور Redux محلی است که state برنامه شما در آن زندگی می‌کند.

index.tsx

import * as React from "react"
import { render } from "react-dom"
import { createStore, applyMiddleware, Store } from "redux"
import { Provider } from "react-redux"
import thunk from "redux-thunk"

import App from "./App"
import reducer from "./store/reducer"

const store: Store<ArticleState, ArticleAction> & {
  dispatch: DispatchType
} = createStore(reducer, applyMiddleware(thunk))

const rootElement = document.getElementById("root")
render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
)

همانطور که مشاهده می‌کنید، تابع reducer را وارد می‌کنیم و سپس آن را به عنوان آرگومان به متد createStore منتقل کرده تا یک استور Redux جدید ایجاد کنیم. میان‌افزار redux-thunk باید به عنوان یک پارامتر دوم و همچنین متد مورد استفاده قرار گیرد تا بتواند کد ناهمگام را مدیریت کند.

در مرحله بعد React را به Redux وصل می‌کنیم.

اکنون می‌توانیم از Redux در این پروژه استفاده کرده و به store دسترسی پیدا کنیم. بنابراین بیایید کامپوننت‌هایی را برای به دست آوردن و دستکاری داده‌ها ایجاد کنیم.

ایجاد کامپوننت‌ها

components/AddArticle.tsx

import * as React from "react"

type Props = {
  saveArticle: (article: IArticle | any) => void
}

export const AddArticle: React.FC<Props> = ({ saveArticle }) => {
  const [article, setArticle] = React.useState<IArticle | {}>()

  const handleArticleData = (e: React.FormEvent<HTMLInputElement>) => {
    setArticle({
      ...article,
      [e.currentTarget.id]: e.currentTarget.value,
    })
  }

  const addNewArticle = (e: React.FormEvent) => {
    e.preventDefault()
    saveArticle(article)
  }

  return (
    <form onSubmit={addNewArticle} className="Add-article">
      <input
        type="text"
        id="title"
        placeholder="Title"
        onChange={handleArticleData}
      />
      <input
        type="text"
        id="body"
        placeholder="Description"
        onChange={handleArticleData}
      />
      <button disabled={article === undefined ? true : false}>
        Add article
      </button>
    </form>
  )
}

برای افزودن بخش جدید، از این کامپوننت فرم استفاده خواهیم کرد. این تابع saveArticle را به عنوان یک پارامتر دریافت می‌کند که به شما امکان می‌دهد بخش جدیدی به store اضافه کنید.

شی article برای استفاده از TypeScript باید از نوع IArticle پیروی کند.

import * as React from "react"
import { Dispatch } from "redux"
import { useDispatch } from "react-redux"

type Props = {
  article: IArticle
  removeArticle: (article: IArticle) => void
}

export const Article: React.FC<Props> = ({ article, removeArticle }) => {
  const dispatch: Dispatch<any> = useDispatch()

  const deleteArticle = React.useCallback(
    (article: IArticle) => dispatch(removeArticle(article)),
    [dispatch, removeArticle]
  )

  return (
    <div className="Article">
      <div>
        <h1>{article.title}</h1>
        <p>{article.body}</p>
      </div>
      <button onClick={() => deleteArticle(article)}>Delete</button>
    </div>
  )
}

کامپوننت Article یک شی article را نشان می‌دهد.

تابع removeArticle باید به store دسترسی پیدا کند و بنابراین article ای را حذف کند. به همین دلیل است که ما از قلاب (hook) useDispatch در اینجا استفاده می‌کنیم که به شما امکان می‌دهد Redux عمل حذف را کامل کند.

در مرحله بعدی، استفاده از useCallback کمک می‌کند تا با یادآوری مقادیر به عنوان وابستگی، از رندر مجدد غیرضروری جلوگیری کنید.

ما سرانجام کامپوننت‌های لازم برای افزودن و نمایش article ها را داریم. بیایید اکنون آخرین بخش را با استفاده از آن در فایل App.tsx به پروژه اضافه کنیم.

App.tsx

import * as React from "react"
import { useSelector, shallowEqual, useDispatch } from "react-redux"
import "./styles.css"

import { Article } from "./components/Article"
import { AddArticle } from "./components/AddArticle"
import { addArticle, removeArticle } from "./store/actionCreators"
import { Dispatch } from "redux"

const App: React.FC = () => {
  const articles: readonly IArticle[] = useSelector(
    (state: ArticleState) => state.articles,
    shallowEqual
  )

  const dispatch: Dispatch<any> = useDispatch()

  const saveArticle = React.useCallback(
    (article: IArticle) => dispatch(addArticle(article)),
    [dispatch]
  )

  return (
    <main>
      <h1>My Articles</h1>
      <AddArticle saveArticle={saveArticle} />
      {articles.map((article: IArticle) => (
        <Article
          key={article.id}
          article={article}
          removeArticle={removeArticle}
        />
      ))}
    </main>
  )
}

export default App

قلاب (hook) useSelector دسترسی به state استور را امکان‌پذیر می‌کند. در اینجا shallowEqual را به عنوان دومین آرگومان به متد منتقل می‌کنیم تا به Redux بگوییم هنگام بررسی تغییرات از برابری سطحی استفاده کند.

در مرحله بعدی برای ارسال action برای افزودن article ها در استور به useDispatch اعتماد میکنیم. در آخر، آرایه article ها را حلقه می‌کنیم و هر کدام را به کامپوننت Article منتقل کرده تا آن را نشان دهیم.

با استفاده از آن، اکنون می‌توانیم روت پروژه را مرور کنیم و سپس این دستور را اجرا کنیم:

 yarn start

یا برای npm:

npm start

اگر http://localhost:3000 را در مرورگر باز کنید، باید این را مشاهده کنید:

برنامه ما خوب به نظر می‌رسد. با این کار، ما اکنون استفاده از Redux را در یک برنامه React TypeScript به پایان رسانده‌ایم.

پروژه به پایان رسیده را می‌توانید در این لینک مشاهده کنید.

امیدواریم از این آموزش لذت کافی را برده باشید. اگر هرگونه سوال یا نظری دارید، آن را در بخش زیر با ما در میان بگذارید.

منبع

گردآوری و تالیف عرفان حشمتی
آفلاین
user-avatar

عرفان حشمتی هستم، مهندس سخت افزار و برنامه نویس و طراح وب سایت، علاقه مند به دنیای آی تی و تکنولوژی، همچنین در حوزه ادیت فیلم و تصویر مطالعه و تمرین می کنم.

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید