كيفية استخدام Redux في تطبيق React TypeScript

Redux عبارة عن حاوية حالة يمكن التنبؤ بها لتطبيقات JavaScript. إنها مكتبة شائعة لإدارة الحالة في تطبيقات React.

يمكن أن يقدم Redux تجربة مطور أفضل عند استخدامه مع TypeScript. TypeScript هي مجموعة شاملة من JavaScript تقوم بفحص التعليمات البرمجية لجعلها قوية ومفهومة.

في هذا الدليل ، سأوضح لك كيفية استخدام Redux في مشروع React TypeScript من خلال إنشاء تطبيق يسمح لك بإضافة المقالات وحذفها وعرضها.

دعنا نتعمق.

  • المتطلبات الأساسية
  • اعداد
  • قم بإنشاء الأنواع
  • قم بإنشاء أنواع الإجراءات
  • إنشاء المبدعين العمل
  • قم بإنشاء مخفض
  • أنشئ متجرًا
  • قم بإنشاء المكونات

المتطلبات الأساسية

يفترض هذا البرنامج التعليمي أن لديك على الأقل فهم أساسي لـ 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المجلد الذي يحتوي على ملفات تتعلق تتفاعل يبعث من جديد.
  • في type.d.tsالملف الذي يحتوي على أنواع نسخة مطبوعة على الآلة الكاتبة، والتي يمكن استخدامها الآن في ملفات أخرى دون المستوردة.

ومع ذلك ، يمكننا الآن تثبيت Redux وإنشاء متجرنا الأول.

لذلك ، لنفتح المشروع ونشغل الأمر التالي:

 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 للمشروع في القسم التالي.

قم بإنشاء الأنواع

تسمح لك أنواع TypeScript بتعيين أنواع للمتغيرات ومعلمات الوظيفة وما إلى ذلك.

  • type.d.ts
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التي ستكون بمثابة أنواع ل، على التوالي، الكائن الدولة، والمبدعين العمل، وظيفة إرسال المقدمة من يبعث من جديد.

ومع ذلك ، لدينا الآن الأنواع الضرورية لبدء استخدام React Redux. لنقم بإنشاء أنواع الإجراءات.

قم بإنشاء أنواع الإجراءات

  • store / actionTypes.ts
export const ADD_ARTICLE = "ADD_ARTICLE" export const REMOVE_ARTICLE = "REMOVE_ARTICLE" 

نحتاج إلى نوعين من الإجراءات لمتجر Redux. واحد لإضافة مقالات وآخر للحذف.

إنشاء المبدعين العمل

  • 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وستقوم الطريقة بالعكس. لذا احذف الكائن الذي تم تمريره كوسيطة.

قم بإنشاء مخفض

المخفض هو وظيفة نقية تستقبل حالة المخزن وإجراء كمعلمات ثم إرجاع الحالة المحدثة.

  • مخزن / المخفض
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", }, ], } 

كما ترون هنا ، نعلن عن حالة أولية تحتوي على بعض المقالات لعرضها عند تحميل الصفحة. يجب أن يتطابق كائن الحالة مع النوع ArticleState- وإلا ، فإن TypeScript ستظهر خطأ.

  • مخزن / المخفض
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 

Next, we have the reducer function that expects the previous state and an action to be able to update the store. Here, we have two actions: one for adding and another for deleting.

With that in place, we can now handle the state with the reducer. Let's now create a store for the project.

Create a store

A Redux store is where your app's state lives.

  • 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 & { dispatch: DispatchType } = createStore(reducer, applyMiddleware(thunk)) const rootElement = document.getElementById("root") render(   , rootElement ) 

As you can see, we import the reducer function and then pass it as an argument to the method createStore in order to create a new Redux store. The redux-thunk middleware needs to be proceeded as a second parameter as well to the method to be able to handle asynchronous code.

Next, we connect React to Redux by providing the store object as props to the Provider component.

We can now use Redux in this project and access the store. So, let's create the components to get and manipulate the data.

Create the components

  • components/AddArticle.tsx
import * as React from "react" type Props =  saveArticle: (article: IArticle  export const AddArticle: React.FC = ({ saveArticle }) => { const [article, setArticle] = React.useState() const handleArticleData = (e: React.FormEvent) => { setArticle({ ...article, [e.currentTarget.id]: e.currentTarget.value, }) } const addNewArticle = (e: React.FormEvent) => { e.preventDefault() saveArticle(article) } return (     Add article   ) } 

To add a new article, we will be using this form component. It receives the function saveArticle as a parameter, which allows adding a new article to the store.

The article object should follow the type IArticle to make TypeScript happy.

  • components/Article.tsx
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 = ({ article, removeArticle }) => { const dispatch: Dispatch = useDispatch() const deleteArticle = React.useCallback( (article: IArticle) => dispatch(removeArticle(article)), [dispatch, removeArticle] ) return ( 

{article.title}

{article.body}

deleteArticle(article)}>Delete ) }

The Article component shows an article object.

The function removeArticle has to dispatch to access the store and hence delete a given article. That's the reason we use the useDispatch hook here, which lets Redux complete the removing action.

Next, the use of useCallback helps to avoid unnecessary re-rendering by memoizing values as dependencies.

We finally have the components we need to add and show the articles. Let's now add the last piece to the puzzle by using them in the App.tsx file.

  • 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 = useDispatch() const saveArticle = React.useCallback( (article: IArticle) => dispatch(addArticle(article)), [dispatch] ) return (  

My Articles

{articles.map((article: IArticle) => ( ))} ) } export default App

The useSelector hook enables access to the state of the store. Here, we pass shallowEqual as a second argument to the method to tell to Redux to use shallow equality when checking for changes.

Next, we rely on useDispatch to dispatch an action for adding articles in the store. Finally, we loop through the array of articles and pass each to the Article component to show it.

With that, we can now browse to the root of the project and then execute this command:

 yarn start 

Or for npm:

 npm start 

If you open //localhost:3000/ in the browser, you should see this:

معاينة التطبيق

Great! Our app looks good. With this, we have now finished using Redux in a React TypeScript app.

يمكنك العثور على المشروع النهائي في CodeSandbox هذا.

يمكنك العثور على محتوى رائع آخر مثل هذا على مدونتي أو متابعتي على Twitter لتلقي إشعارات.

شكرا للقراءة.