Redux Toolkit 快速入門
- 如何設定和使用 Redux Toolkit 搭配 React-Redux
簡介
歡迎使用 Redux Toolkit 快速入門教學!本教學課程將簡要介紹 Redux Toolkit,並教您如何開始正確使用它。
如何閱讀本教學課程
本頁面將重點介紹如何使用 Redux Toolkit 設定 Redux 應用程式,以及您將使用的主要 API。如需了解 Redux 是什麼、其運作方式,以及如何使用 Redux Toolkit 的完整範例,請參閱「教學課程總覽」頁面中連結的教學課程。
在本教學課程中,我們假設您將 Redux Toolkit 與 React 搭配使用,但您也可以將它與其他 UI 層搭配使用。這些範例基於 典型的 Create-React-App 資料夾結構,其中所有應用程式程式碼都位於 src
中,但這些模式可以調整為您使用的任何專案或資料夾設定。
適用於 Create-React-App 的 Redux+JS 範本附帶已設定好的相同專案設定。
使用摘要
安裝 Redux Toolkit 和 React-Redux
將 Redux Toolkit 和 React-Redux 套件新增到您的專案
npm install @reduxjs/toolkit react-redux
建立 Redux Store
建立一個名為 src/app/store.js
的檔案。從 Redux Toolkit 匯入 configureStore
API。我們將從建立一個空的 Redux store 開始,並將其匯出
- TypeScript
- JavaScript
import { configureStore } from '@reduxjs/toolkit'
export const store = configureStore({
reducer: {},
})
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
import { configureStore } from '@reduxjs/toolkit'
export const store = configureStore({
reducer: {},
})
這會建立一個 Redux store,並自動設定 Redux DevTools 擴充功能,以便您在開發時檢查 store。
提供 Redux Store 給 React
建立 store 之後,我們可以透過在 src/index.js
中的應用程式周圍放置 React-Redux <Provider>
,讓 React 元件可以使用它。匯入我們剛剛建立的 Redux store,在 <App>
周圍放置一個 <Provider>
,並將 store 傳遞為 prop
- TypeScript
- JavaScript
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { store } from './app/store'
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { store } from './app/store'
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
建立 Redux 狀態區段
新增一個名為 src/features/counter/counterSlice.js
的檔案。在該檔案中,從 Redux Toolkit 匯入 createSlice
API。
建立區段需要一個字串名稱來識別區段、一個初始狀態值,以及一個或多個 reducer 函式來定義如何更新狀態。建立區段後,我們可以匯出產生的 Redux 動作建立器和整個區段的 reducer 函式。
Redux 要求我們透過複製資料並更新副本,以不可變的方式撰寫所有狀態更新。然而,Redux Toolkit 的 createSlice
和 createReducer
API 在內部使用 Immer,讓我們能夠撰寫「變異」更新邏輯,並轉換成正確的不可變更新。
- TypeScript
- JavaScript
import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
export interface CounterState {
value: number
}
const initialState: CounterState = {
value: 0,
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
},
})
// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
value: 0,
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})
// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
將區段 Reducer 加入 Store
接下來,我們需要從 counter 區段匯入 reducer 函式,並將其加入我們的 store。透過在 reducer
參數內定義一個欄位,我們告知 store 使用此區段 reducer 函式來處理該狀態的所有更新。
- TypeScript
- JavaScript
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
在 React 元件中使用 Redux 狀態和動作
現在,我們可以使用 React-Redux 勾子讓 React 元件與 Redux store 互動。我們可以使用 useSelector
從 store 讀取資料,並使用 useDispatch
派送動作。建立一個 src/features/counter/Counter.js
檔案,其中包含一個 <Counter>
元件,然後將該元件匯入 App.js
並在 <App>
內部渲染它。
- TypeScript
- JavaScript
import React from 'react'
import type { RootState } from '../../app/store'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
export function Counter() {
const count = useSelector((state: RootState) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
export function Counter() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
現在,任何時候你按一下「遞增」和「遞減」按鈕
- 對應的 Redux 動作將派送至 store
- counter 區段 reducer 將看到動作並更新其狀態
<Counter>
元件將看到 store 中的新狀態值,並使用新資料重新渲染自身
你學到了什麼
這是如何設定和使用 Redux Toolkit 與 React 的簡要概述。回顧一下細節
- 使用
configureStore
建立 Redux storeconfigureStore
接受一個reducer
函式作為命名參數configureStore
會自動設定儲存庫,並使用良好的預設設定
- 將 Redux 儲存庫提供給 React 應用程式元件
- 在
<App />
周圍放置一個 React-Redux<Provider>
元件 - 傳遞 Redux 儲存庫作為
<Provider store={store}>
- 在
- 使用
createSlice
建立一個 Redux 「區塊」reducer- 使用字串名稱、初始狀態和命名 reducer 函式呼叫
createSlice
- reducer 函式可以使用 Immer「變異」狀態
- 匯出產生的區塊 reducer 和動作建立器
- 使用字串名稱、初始狀態和命名 reducer 函式呼叫
- 在 React 元件中使用 React-Redux
useSelector/useDispatch
勾子- 使用
useSelector
勾子從儲存庫中讀取資料 - 使用
useDispatch
勾子取得dispatch
函式,並視需要發送動作
- 使用
完整的計數器應用程式範例
這裡顯示的計數器範例應用程式也是
以下是完整的計數器應用程式,作為執行的 CodeSandbox
接下來是什麼?
我們建議瀏覽 Redux 核心文件中的「Redux Essentials」和「Redux Fundamentals」教學課程,這將讓你完全了解 Redux 的運作方式、Redux Toolkit 的功能以及如何正確使用它。