A Redux egy kiszámítható állapotú tároló a JavaScript-alkalmazásokhoz. Ez egy népszerű könyvtár az állapot kezelésére a React alkalmazásokban.
A Redux jobb fejlesztői élményt kínál, ha a TypeScript-szel együtt használja. A TypeScript a JavaScript egy olyan halmaza, amely típusellenőrzi a kódot, hogy robusztus és érthető legyen.
Ebben az útmutatóban megmutatom, hogyan használhatja a Redux-ot a React TypeScript projektben egy olyan alkalmazás létrehozásával, amely lehetővé teszi cikkek hozzáadását, törlését és megjelenítését.
Merüljünk be.
- Előfeltételek
- Felállítása
- Hozza létre a típusokat
- Hozza létre a művelettípusokat
- Hozza létre az akciókészítőket
- Hozzon létre egy reduktort
- Hozzon létre egy üzletet
- Hozza létre az összetevőket
Előfeltételek
Ez az oktatóanyag feltételezi, hogy legalább alaposan ismeri a React, a Redux és a TypeScript ismereteit.
Tehát, ha még nem ismeri ezeket a technológiákat, először próbálja meg elolvasni ezt a gyakorlati útmutatót a TypeScript-hez vagy ezt a React Redux oktatóanyagot. Ellenkező esetben kezdjük.
A projekt beállítása
A Redux és a TypeScript használatához létre kell hoznunk egy új React alkalmazást.
Ehhez nyissuk meg a CLI-t (parancssori felület), és hajtsuk végre ezt a parancsot:
npx create-react-app my-app --template typescript
Ezután strukturáljuk a projektet az alábbiak szerint:
├── 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
A projekt fájlszerkezete meglehetősen egyszerű. Két dolgot kell azonban megjegyezni:
- A
store
React Redux fájlhoz kapcsolódó fájlokat tartalmazó mappa. - A
type.d.ts
TypeScript típusokat tartalmazó fájl, amelyet importálás nélkül más fájlokban is fel lehet használni.
Ez azt jelenti, hogy most telepíthetjük a Redux-et és létrehozhatjuk az első üzletünket.
Tehát nyissuk meg a projektet, és futtassuk a következő parancsot:
yarn add redux react-redux redux-thunk
Vagy használatakor npm
npm install redux react-redux redux-thunk
A típusokat fejlesztési függőségként is telepítenünk kell, hogy a TypeScript megértsék a könyvtárakat.
Tehát hajtsuk végre újra ezt a parancsot a CLI-n.
yarn add -D @types/redux @types/react-redux @types/redux-thunk
Vagy npm
:
npm install -D @types/redux @types/react-redux @types/redux-thunk
Nagy! Ezzel az előrelépéssel most létrehozhatjuk a TypeScript típusokat a projekthez a következő szakaszban.
Hozza létre a típusokat
A TypeScript típusok lehetővé teszik a változók, a funkcióparaméterek stb. Típusainak beállítását.
- típus.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
Itt kezdjük az interfész deklarálásával, IArticle
amely tükrözi az adott cikk alakját.
Ezután megvan a ArticleState
, ArticleAction
és DispatchType
ez a Redux által biztosított állapotobjektum, az akciókészítők és a diszpécser függvény típusaként szolgál.
Ez azt jelenti, hogy megvan a szükséges típus a React Redux használatának megkezdéséhez. Hozzuk létre a művelettípusokat.
Hozza létre a művelettípusokat
- store / actionTypes.ts
export const ADD_ARTICLE = "ADD_ARTICLE" export const REMOVE_ARTICLE = "REMOVE_ARTICLE"
Két művelettípusra van szükségünk a Redux áruházhoz. Az egyik cikkek hozzáadásához, a másik pedig törléshez.
Hozza létre az akciókészítőket
- 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) } }
Ebben az oktatóanyagban szimulálom a HTTP kérést úgy, hogy késleltetem 0,5 másodpercig. De nyugodtan használjon valódi szervert, ha akarja.
Itt a függvény addArticle
műveletet küld egy új cikk hozzáadásához, és a módszer removeArticle
ennek ellenkezőjét fogja tenni. Tehát törölje az argumentumként átadott objektumot.
Hozzon létre egy reduktort
A reduktor egy tiszta függvény, amely paraméterként fogadja a tár és egy művelet állapotát, majd visszaadja a frissített állapotot.
- bolt / reduktor.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", }, ], }
Amint itt láthatja, deklarálunk egy kezdeti állapotot, hogy néhány cikk megjelenjen az oldal betöltésekor. Az állapotobjektumnak meg kell egyeznie a típussal ArticleState
- ellenkező esetben a TypeScript hibát dob.
- bolt / reduktor.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
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.
You can find the finished project in this CodeSandbox.
You can find other great content like this on my blog or follow me on Twitter to get notified.
Thanks for reading.