Hướng dẫn sử dụng Redux Toolkit với TypeScript

theanh

Administrator
Nhân viên
Nếu bạn là một nhà phát triển React đang làm việc trên một ứng dụng phức tạp, bạn sẽ cần sử dụng quản lý trạng thái toàn cục cho ứng dụng của mình tại một thời điểm nào đó. React Redux là một trong những thư viện phổ biến nhất để quản lý trạng thái được nhiều nhà phát triển sử dụng. Tuy nhiên, React Redux có quy trình thiết lập phức tạp mà tôi thấy không hiệu quả, chưa kể đến việc nó yêu cầu rất nhiều mã mẫu. Nhà phát triển chính thức của Redux đã phát triển Redux Toolkit để đơn giản hóa quy trình.

Bài viết này dành cho những người có đủ kiến thức về React và TypeScript để làm việc với Redux.

Giới thiệu về Redux​

Redux là thư viện quản lý trạng thái toàn cục cho các ứng dụng React. Nếu bạn đã sử dụng các hook useState() để quản lý trạng thái ứng dụng, bạn sẽ thấy khó truy cập trạng thái khi cần trong các phần khác của ứng dụng. Với các hook useState(), trạng thái có thể được truyền từ thành phần cha sang thành phần con và bạn sẽ gặp phải vấn đề prop drilling nếu bạn cần truyền nó cho nhiều thành phần con. Đó là lúc Redux xuất hiện để quản lý trạng thái ứng dụng.

Giới thiệu về Redux Toolkit​

Redux Toolkit là một tập hợp các công cụ có chủ kiến và chuẩn hóa giúp đơn giản hóa quá trình phát triển ứng dụng bằng cách sử dụng thư viện quản lý trạng thái Redux.
Nó loại bỏ nhu cầu viết mã thiết lập Redux chuẩn, chẳng hạn như định nghĩa hành động, bộ giảm tốc và cấu hình lưu trữ, có thể là một lượng mã đáng kể để viết và duy trì.

Jerry Navi có một hướng dẫn tuyệt vời cho thấy toàn bộ quy trình thiết lập Redux.

Tại sao tôi thích Redux Toolkit hơn Redux​

Redux Toolkit có một số tính năng chính khiến tôi sử dụng thư viện này thay vì Redux thông thường:
  1. Định nghĩa bộ giảm tốc
    Với Redux Toolkit, bạn có thể chỉ định một lát cắt với một vài dòng mã để định nghĩa bộ giảm tốc thay vì định nghĩa hành động và bộ giảm tốc riêng biệt, như Redux.
  2. Trợ giúp bất biến
    Redux Toolkit bao gồm một tập hợp các hàm tiện ích giúp dễ dàng để cập nhật các đối tượng và mảng theo cách không thay đổi. Điều này giúp việc viết mã tuân theo các nguyên tắc bất biến của Redux trở nên đơn giản hơn.
  3. Phần mềm trung gian tích hợp
    Redux Toolkit bao gồm phần mềm trung gian tích hợp có thể xử lý các tác vụ yêu cầu không đồng bộ.
  4. Tích hợp DevTools
    Redux Toolkit bao gồm tích hợp với tiện ích mở rộng trình duyệt Redux DevTools, giúp gỡ lỗi và phân tích mã Redux dễ dàng hơn.

Sử dụng Redux Toolkit để xây dựng Trình theo dõi sự cố của dự án​

Tôi nghĩ cách tốt nhất để giải thích giá trị và lợi ích của việc sử dụng Redux Toolkit là chỉ cho bạn thấy chúng trong bối cảnh thực tế. Vậy thì, hãy cùng phát triển một ứng dụng được thiết kế để tạo và theo dõi các sự cố GitHub.



Bạn có thể theo dõi các ví dụ về mã khi chúng tôi thực hiện và tham khảo mã đầy đủ bất kỳ lúc nào bằng cách lấy mã đó từ GitHub. Ngoài ra còn có triển khai trực tiếp ví dụ này mà bạn có thể xem.

Bắt đầu tạo ứng dụng React mới bằng lệnh sau:
Mã:
yarn create react-app project_issue_tracker --template typescript
Lệnh này tạo một thư mục cho dự án của chúng ta với các tệp cơ bản mà chúng ta cần để phát triển. Phần –template typescript của lệnh được sử dụng để thêm TypeScript vào ngăn xếp.

Bây giờ, hãy cài đặt các gói phụ thuộc cần thiết cho dự án của chúng ta và xây dựng giao diện người dùng chính cho ứng dụng trước khi triển khai Redux Toolkit. Trước tiên, hãy điều hướng đến thư mục dự án project_issue_tracker mà chúng ta vừa tạo:
Mã:
cd project_issue_tracker
Sau đó, chạy lệnh sau để cài đặt Material UIEmotion, trong đó thư viện trước là thư viện thiết kế mà chúng ta có thể sử dụng để tạo kiểu cho các thành phần và thư viện sau cho phép viết CSS trong các tệp JavaScript.
Mã:
yarn add @mui/material @emotion/react @emotion/styled
Bây giờ chúng ta có thể cài đặt Redix Toolkit và Redux:
Mã:
yarn add @reduxjs/toolkit react-redux
Chúng ta đã có mọi thứ cần thiết để bắt đầu phát triển! Chúng ta có thể bắt đầu bằng cách xây dựng giao diện người dùng.

Phát triển giao diện người dùng​

Trong phần này, chúng ta sẽ phát triển giao diện người dùng của ứng dụng. Mở thư mục dự án chính và tạo một thư mục con components mới trực tiếp trong thư mục gốc. Bên trong thư mục mới này, tạo một tệp mới có tên là ProjectCard.tsx. Đây là nơi chúng ta sẽ viết mã cho thành phần ProjectCard chứa thông tin về sự cố đang mở trong trình theo dõi sự cố của dự án.

Hãy nhập một số thành phần thiết kế từ gói Material UI mà chúng ta đã cài đặt vào tệp /components/ProjectCard.tsx mới để bắt đầu:
Mã:
import React from "react";import { Typography, Grid, Stack, Paper} from "@mui/material";giao diện IProps { issueTitle: chuỗi}const ProjectCard : React.FC = ({ issueTitle }) => { return(  
     Tiêu đề số báo: {issueTitle}    Đã mở: hôm qua   Mức độ ưu tiên: trung bình        )}export default ProjectCard;
Điều này tạo ra thẻ dự án hiển thị tiêu đề sự cố, mức độ ưu tiên của sự cố và thời gian sự cố được "mở". Lưu ý rằng chúng ta đang sử dụng một prop issueTitle sẽ được chuyển đến thành phần ProjectCard để hiển thị sự cố với tiêu đề được cung cấp.

Bây giờ, hãy tạo thành phần cho HomePage của ứng dụng để hiển thị tất cả các sự cố. Chúng ta sẽ thêm một biểu mẫu nhỏ vào trang để gửi các sự cố mới có chứa trường văn bản để nhập tên sự cố và một nút để gửi biểu mẫu. Chúng ta có thể thực hiện điều đó bằng cách mở tệp src/HomePage.tsx trong thư mục dự án và nhập hook useState của React, một vài thành phần được tạo kiểu khác từ Material UI và thành phần ProjectCard mà chúng ta đã thiết lập trước đó:
Mã:
import React, { useState } from "react";import { Box, Typography, TextField, Stack, Button } from "@mui/material";import ProjectCard from "./components/ProjectCard";const HomePage = () => { const [textInput, setTextInput] = useState(''); const handleTextInputChange = (e:any) => { setTextInput(e.target.value); }; return(    Trình theo dõi sự cố của dự án     Thêm sự cố mới   Submit     Sự cố đã mở  
     )}export default HomePage;
Điều này dẫn đến một thành phần HomePage mới mà người dùng có thể tương tác để thêm sự cố mới bằng cách nhập tên sự cố vào mục nhập văn bản biểu mẫu. Khi vấn đề được gửi đi, một thành phần ProjectCard mới sẽ được thêm vào HomePage, đóng vai trò như một chỉ mục để xem tất cả các vấn đề đang mở.

Việc duy nhất còn lại đối với giao diện là hiển thị HomePage, chúng ta có thể thực hiện bằng cách thêm nó vào tệp App.tsx. Toàn bộ mã có sẵn tại đây trên GitHub.

Sử dụng Redux Toolkit​

Bây giờ UI của chúng ta đã hoàn thiện, chúng ta có thể chuyển sang triển khai Redux Toolkit để quản lý trạng thái của ứng dụng này. Chúng ta sẽ sử dụng Redux Toolkit để quản lý trạng thái của danh sách ProjectCard bằng cách lưu trữ tất cả các vấn đề trong một cửa hàng có thể truy cập từ bất kỳ đâu trong ứng dụng.

Trước khi chuyển sang phần triển khai thực tế, hãy cùng tìm hiểu một số khái niệm của Redux Toolkit để giúp hiểu những gì chúng ta đang triển khai:
  1. createSlice
    Hàm này giúp dễ dàng xác định bộ giảm, hành động và initialState trong một đối tượng. Không giống như redux thông thường, bạn không cần sử dụng công tắc cho các hành động và cần xác định các hành động riêng biệt. Hàm này chấp nhận một đối tượng làm tên (tức là tên của lát cắt) và trạng thái ban đầu của store và reducer, trong đó bạn định nghĩa tất cả các reducer cùng với các loại hành động của chúng.
  2. configureStore
    Hàm này là một phép trừu tượng cho hàm createStore() của Redux. Nó loại bỏ sự phụ thuộc của việc định nghĩa các reducer riêng biệt và tạo lại store. Theo cách này, store được cấu hình tự động và có thể được chuyển đến Provider.
  3. createAsyncThunk
    Hàm này đơn giản hóa việc thực hiện các cuộc gọi không đồng bộ. Nó tự động phân phối nhiều hành động khác nhau để quản lý trạng thái của các cuộc gọi và cung cấp một cách chuẩn hóa để xử lý lỗi.
Hãy triển khai tất cả những điều này! Chúng ta sẽ tạo issueReducer bằng hành động addIssue() để thêm bất kỳ sự cố mới nào được gửi vào store projectIssues. Bạn có thể thực hiện việc này bằng cách tạo một tệp mới trong src/redux/ có tên là IssueReducer.ts với mã này:
Mã:
// Phần 1import { createSlice, PayloadAction } from "@reduxjs/toolkit"// Phần 2export interface IssueInitialState { projectIssues: string[]}const initialState: IssueInitialState = { projectIssues: []}// Phần 3export const issueSlice = createSlice({ name: 'issue', initialState, reducers: { addIssue: (state, action: PayloadAction) => { state.projectIssues = [...state.projectIssues, action.payload] } }})// Phần 4export const { addIssue } = issueSlice.actionsexport default issueSlice.reducer
Hãy cùng tìm hiểu từng phần của mã. Đầu tiên, chúng ta sẽ nhập các hàm cần thiết từ gói @reduxjs/toolkit của Redux.

Sau đó, chúng ta tạo định nghĩa kiểu cho trạng thái ban đầu và khởi tạo initialState cho issueReducer. initialState có danh sách projectIssues[] sẽ được sử dụng để lưu trữ tất cả các sự cố đã gửi. Chúng ta có thể có nhiều thuộc tính được xác định trong initialState tùy theo nhu cầu của ứng dụng.

Thứ ba, chúng ta sẽ xác định issueSlice bằng hàm createSlice của Redux Toolkit, hàm này có logic của issueReducer cũng như các hành động khác nhau liên quan đến hàm này. createSlice chấp nhận một đối tượng có một số thuộc tính, bao gồm:
  • name: tên của lát cắt,
  • initialState: trạng thái ban đầu của hàm reducer,
  • reducers: một đối tượng chấp nhận các hành động khác nhau mà chúng ta muốn xác định cho reducer của mình.
Tên lát cắt cho issueReducerissueSlice. initalState của lát cắt này được xác định và một hành động adIssue duy nhất được liên kết với lát cắt này. Hành động addIssue được phân phối bất cứ khi nào có một vấn đề mới được gửi. Chúng ta cũng có thể xác định các hành động khác nếu ứng dụng yêu cầu, nhưng đây là tất cả những gì chúng ta cần cho ví dụ này.

Cuối cùng, trong phần cuối cùng của mã, chúng ta xuất các hành động được liên kết với reducer và reducer issueSlice của mình. Chúng tôi đã triển khai đầy đủ issueReducer, lưu trữ tất cả các sự cố đã gửi bằng cách gửi hành động addIssue.

Bây giờ hãy cấu hình issueReducer trong kho lưu trữ của chúng ta để chúng ta có thể sử dụng nó trong ứng dụng. Tạo một tệp mới trong src/redux/ có tên là index.ts và thêm mã sau:
Mã:
import { configureStore } from "@reduxjs/toolkit";import IssueReducer from "./IssueReducer";export const store = configureStore({ reducer: { issue: IssueReducer }})export type RootState = ReturnTypeexport type AppDispatch = typeof store.dispatch
Đoạn mã này định cấu hình và tạo store bằng hàm configureStore() chấp nhận một reducer mà chúng ta có thể truyền tất cả các reducer khác nhau.

Chúng ta đã hoàn tất việc thêm reducer và định cấu hình store bằng Redux Toolkit. Hãy thực hiện bước cuối cùng là truyền store cho ứng dụng của chúng ta. Bắt đầu bằng cách cập nhật tệp App.tsx để truyền store bằng Provider:
Mã:
import React from 'react';import { Provider } from "react-redux"import { store } from './redux';import HomePage from './HomePage';function App() { return (  
    );}export default App;
Tại đây, bạn có thể thấy chúng ta đang nhập store và truyền trực tiếp qua Provider. Chúng ta không cần phải viết thêm bất cứ thứ gì để tạo store hoặc cấu hình DevTools như khi sử dụng Redux thuần túy. Đây chắc chắn là một trong những cách Redux Toolkit hợp lý hóa mọi thứ.

OK, chúng ta đã thiết lập thành công store và reducer cho ứng dụng của mình bằng Redux Toolkit. Bây giờ, hãy sử dụng ứng dụng của chúng ta và xem nó có hoạt động không. Để tóm tắt nhanh mọi thứ, hàm dispatch() được sử dụng để phân phối bất kỳ hành động nào đến kho lưu trữ và useSelector() được sử dụng để truy cập bất kỳ thuộc tính trạng thái nào.

Chúng ta sẽ phân phối hành động addIssue khi nhấp vào nút biểu mẫu:
Mã:
const handleClick = () => { dispatch(addIssue(textInput))}
Để truy cập danh sách projectIssue được lưu trữ trong kho lưu trữ bộ giảm tốc của chúng ta, chúng ta có thể sử dụng useSelector() như sau:
Mã:
const issueList = useSelector((state: RootState) => state.issue.projectIssues)
Cuối cùng, chúng ta có thể hiển thị tất cả các vấn đề bằng cách map()-ping issueList đến thành phần ProjectCard:
Mã:
{ issueList.map((issue) => { return( 
 ) })}
Mã cuối cùng cho HomePage.tsx trông như sau:
Mã:
import React, { useState } từ "react";import { useDispatch, useSelector } từ "react-redux";import { RootState } từ "./redux/index"import { Box, Typography, TextField, Stack, Button } từ "@mui/material";import ProjectCard từ "./components/ProjectCard";import { addIssue } từ "./redux/IssueReducer";const HomePage = () => { const dispatch = useDispatch(); const issueList = useSelector((state: RootState) => state.issue.projectIssues) const [textInput, setTextInput] = useState(''); const handleTextInputChange = (e:any) => { setTextInput(e.target.value); }; const handleClick = () => { dispatch(addIssue(textInput)) } return(    Project Issue Tracker     Thêm sự cố mới   Submit     Opened issue  { issueList.map((issue) => { return( 
 ) }) }    )}export default HomePage;
Bây giờ, khi chúng ta thêm và gửi một vấn đề bằng biểu mẫu, vấn đề đó sẽ được hiển thị trên trang chủ.

Phần này đề cập đến cách định nghĩa bất kỳ bộ giảm tốc nào và cách chúng được sử dụng trong ứng dụng. Phần sau đây sẽ trình bày cách Redux Toolkit thực hiện các cuộc gọi không đồng bộ một cách tương đối đơn giản.

Thực hiện các cuộc gọi không đồng bộ bằng Redux Toolkit​

Chúng tôi đã triển khai store của mình để lưu và hiển thị bất kỳ sự cố nào mới được thêm vào ứng dụng của mình. Nếu chúng tôi muốn gọi GitHub API cho bất kỳ kho lưu trữ nào và liệt kê tất cả các sự cố của kho lưu trữ đó trong ứng dụng của mình thì sao? Trong phần này, chúng ta sẽ xem cách sử dụng API createAsyncThunk() với slice để lấy dữ liệu và hiển thị tất cả các sự cố của kho lưu trữ bằng cách sử dụng lệnh gọi API.

Tôi luôn thích sử dụng API createAsyncThunk() của bộ công cụ redux vì nó chuẩn hóa cách xử lý các trạng thái khác nhau, chẳng hạn như đang tải, lỗiđã hoàn tất. Một lý do khác là chúng tôi không cần thêm cấu hình bổ sung cho phần mềm trung gian.

Trước tiên, hãy thêm mã để tạo trình giảm GithubIssue trước khi chúng ta phân tích nó để hiểu những gì đang diễn ra. Thêm tệp GithubIssueReducer.ts mới vào thư mục /redux và thêm mã này:
Mã:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';export const fetchIssues = createAsyncThunk( "githubIssue/fetchIssues", async (_, thunkAPI) => { try { const response = await fetch("https://api.github.com/repos/github/hub/issues"); const data = await response.json(); const issues = data.map((issue: { title: string }) => issue.title); return issues; } catch (error) { return thunkAPI.rejectWithValue("Không thể tìm nạp các vấn đề."); } });interface IssuesState { issues: string[]; loading: boolean; error: string | null;}const initialState: IssuesState = { issues: [], loading: false, error: null,};export const issuesSliceGithub = createSlice({ name: 'github_issues', initialState, reducers: {}, extraReducers: (builder) => { builder .addCase(fetchIssues.pending, (state) => { state.loading = true; state.error = null; }) .addCase(fetchIssues.fulfilled, (state, action) => { state.loading = false; state.issues = action.payload; }) .addCase(fetchIssues.rejected, (state, action) => { state.loading = false; state.error = action.error.message || 'Đã xảy ra lỗi'; }); },});export default issuesSliceGithub.reducer;
Trước tiên, hãy cùng tìm hiểu phần fetchIssues:
  1. Chúng ta đang sử dụng API createAsyncThunk() do Redux Toolkit cung cấp. API này giúp tạo các hành động bất đồng bộ và xử lý trạng thái tải và lỗi của ứng dụng.
  2. Tên loại hành động là đối số đầu tiên được truyền cho createAsyncThunk(). Tên loại hành động cụ thể mà chúng ta đã định nghĩa là githubIssue/fetchIssues.
  3. Đối số thứ hai là một hàm trả về Promise, giải quyết thành giá trị phân phối hành động. Đây là lúc hàm bất đồng bộ truy xuất dữ liệu từ điểm cuối GitHub API và ánh xạ dữ liệu phản hồi vào danh sách tiêu đề sự cố.
  4. Đối số thứ ba là một đối tượng chứa các tùy chọn cấu hình cho async thunk. Trong trường hợp này, chúng tôi đã chỉ định rằng async thunk sẽ không được phân phối với bất kỳ đối số nào (do đó có kiểu void) và nếu Promise do hàm async trả về bị từ chối, async thunk sẽ trả về một hành động có trạng thái bị từ chối cùng với thuộc tính rejectValue chứa chuỗi "Không tìm nạp được sự cố".
Khi hành động này được phân phối, các lệnh gọi API sẽ được thực hiện và dữ liệu githubIssuesList sẽ được lưu trữ. Chúng ta có thể làm theo chính xác trình tự các bước này để thực hiện bất kỳ lệnh gọi API nào mà chúng ta cần.

Phần thứ hai của mã tương tự như phần chúng ta đã sử dụng khi tạo issueSlice, nhưng có ba điểm khác biệt:
  1. extraReducers
    Đối tượng này chứa logic bộ giảm tốc cho các bộ giảm tốc không được xác định trong đối tượng bộ giảm tốc createSlice. Nó lấy một đối tượng xây dựng trong đó các trường hợp khác nhau có thể được thêm bằng addCase cho các loại hành động cụ thể.
  2. addCase
    Phương pháp này trên đối tượng xây dựng tạo một trường hợp mới cho hàm giảm.
  3. Trạng thái gọi API
    Hàm gọi lại được truyền cho phương thức addCase được phân phối bởi createAsyncThunk(), hàm này cập nhật các đối tượng lưu trữ khác nhau dựa trên các trạng thái gọi API (đang chờ xử lý, đã hoàn tấtlỗi).
Bây giờ chúng ta có thể sử dụng các hành động giảm GithubIssue và cửa hàng trong ứng dụng của mình. Trước tiên, hãy thêm GithubIssueReducer vào cửa hàng của chúng ta. Cập nhật tệp /redux/index.ts bằng mã này:
Mã:
import { configureStore } từ "@reduxjs/toolkit";import { useDispatch } từ "react-redux";import IssueReducer từ "./IssueReducer";import GithubIssueReducer từ "./GithubIssueReducer";export const store = configureStore({ reducer: { issue: IssueReducer, githubIssue: GithubIssueReducer }})export type RootState = ReturnTypeexport type AppDispatch = typeof store.dispatchexport const useAppDispatch = () => useDispatch()
Chúng tôi vừa thêm GithubIssueReducer vào cửa hàng của mình với tên được ánh xạ tới githubIssue. Bây giờ chúng tôi có thể sử dụng bộ giảm tốc này trong thành phần HomePage của mình để phân phối fetchIssues() và điền vào trang của chúng tôi tất cả các sự cố nhận được từ kho lưu trữ GitHub API.
Mã:
import React, { useState, useEffect } from "react";import { useSelector } from "react-redux";import { useAppDispatch, RootState, AppDispatch } from "./redux/index";import { Box, Typography, TextField, Stack, Button } from "@mui/material";import ProjectCard from "./components/ProjectCard";import { addIssue } từ "./redux/IssueReducer";import { fetchIssues } từ "./redux/GithubIssueReducer";const Trang chủ = () => {const dispatch: AppDispatch = useAppDispatch(); const [textInput, setTextInput] = useState(''); const githubIssueList = useSelector((trạng thái: RootState) => state.githubIssue.issues) const loading = useSelector((trạng thái: RootState) => state.githubIssue.loading); const error = useSelector((trạng thái: RootState) => state.githubIssue.error); useEffect(() => { dispatch(fetchIssues()) }, [dispatch]); nếu (đang tải) { trả về Đang tải...; } nếu (lỗi) { trả về Lỗi: {lỗi}; } const handleTextInputChange = (e:any) => { setTextInput(e.target.value); }; const handleClick = () => { console.log(textInput) dispatch(addIssue(textInput)) } return(    Project Issue Tracker     Thêm sự cố mới   Submit     Opened issue  { githubIssueList?.map((issue : string) => { return( 
 ) }) }    )}export default HomePage;
Điều này cập nhật mã trong HomePage.tsx với hai thay đổi nhỏ:
  1. Chúng tôi phân phối fetchIssue và sử dụng Hành động createAsync() để thực hiện các lệnh gọi API dưới hook useEffect.
  2. Chúng tôi sử dụng các trạng thái loadingerror khi thành phần được hiển thị.
Bây giờ, khi tải ứng dụng, trước tiên bạn sẽ thấy văn bản "Đang tải" được hiển thị và sau khi lệnh gọi API được thực hiện, issuesList sẽ được điền bằng tất cả các tiêu đề của các sự cố GitHub được lấy từ kho lưu trữ.

Một lần nữa, mã hoàn chỉnh cho dự án này có thể được tìm thấy trên GitHub. Bạn cũng có thể kiểm tra triển khai trực tiếp của ứng dụng, hiển thị tất cả các sự cố được lấy từ GitHub.

Kết luận​

Vậy là xong! Chúng tôi đã sử dụng Redux Toolkit trong ứng dụng React TypeScript để xây dựng trình theo dõi sự cố dự án đầy đủ chức năng, đồng bộ với GitHub và cho phép chúng tôi tạo sự cố mới trực tiếp từ ứng dụng.

Chúng tôi đã học được nhiều khái niệm cơ bản của Redux Toolkit, chẳng hạn như định nghĩa bộ giảm tốc, trình trợ giúp bất biến, phần mềm trung gian tích hợp và tích hợp DevTools. Tôi hy vọng bạn cảm thấy có đủ năng lực để sử dụng Redux Toolkit hiệu quả trong các dự án của mình. Với Redux Toolkit, bạn có thể cải thiện hiệu suất và khả năng mở rộng của các ứng dụng React bằng cách quản lý hiệu quả trạng thái toàn cục.

Đọc thêm trên Smashing Magazine​

  • Redux Reducers hoạt động như thế nào, Fortune Ikechi
  • Redux là gì: Hướng dẫn dành cho nhà thiết kế, Linton Ye
  • Kiểu tĩnh động trong TypeScript, Stefan Baumgartner
  • Đi sâu vào giao diện người dùng không có máy chủ với TypeScript, Ikeh Akinyemi
  • Thiết lập Redux để sử dụng trong ứng dụng thực tế, Jerry Navi
 
Back
Bên trên