Redux Toolkit 快速入门
- 如何设置并使用 Redux Toolkit 和 React-Redux
- 熟悉 ES6 语法和特性
- 了解 React 术语:JSX,State,函数组件,Props 和 Hooks
- 理解 Redux 术语和概念
介绍
欢迎来到 Redux Toolkit 快速入门教程!本教程将简要介绍 Redux Toolkit 并教你如何正确使用它。
如何阅读本教程
本页将重点介绍如何使用 Redux Toolkit 设置 Redux 应用程序以及你将使用的主要 API。关于 Redux 是什么,它是如何工作的,以及如何使用 Redux Toolkit 的完整示例,请参阅"教程概览"页面中的链接教程。
对于本教程,我们假设你正在使用 Redux Toolkit 与 React,但你也可以将其与其他 UI 层一起使用。示例基于 典型的 Create-React-App 文件结构,其中所有应用程序代 码都在 src
中,但这些模式可以适应你正在使用的任何项目或文件夹设置。
Redux+JS 的 Create-React-App 模板已经配置了相同的项目设置。
使用总结
安装 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,并导出它:
import { configureStore } from '@reduxjs/toolkit'
export const store = configureStore({
reducer: {},
})
// 从 store 本身推断 `RootState` 和 `AppDispatch` 类型
export type RootState = ReturnType<typeof store.getState>
// 推断的类型:{posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
这将创建一个 Redux store,并自动配置 Redux DevTools 扩展,以便你在开发时可以检查 store。
为 React 提供 Redux Store
一旦 store 被创建,我们可以通过在我们的应用程序 src/index.js
中放置一个 React-Redux 的 <Provider>
来使其对我们的 React 组件可用。导入我们刚刚创建的 Redux store,将 <Provider>
放在你的 <App>
周围,并将 store 作为一个 prop 传递:
// 文件: App.tsx noEmit
import React from 'react'
export default function App() {
return <div>...</div>
}
// 文件: app/store.ts noEmit
import { configureStore } from '@reduxjs/toolkit'
export const store = configureStore({
reducer: {},
})
// 文件: index.tsx
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 State Slice
添加一个新文件名为 src/features/counter/counterSlice.js
。在该文件中,从 Redux Toolkit 导入 createSlice
API。
创建一个 slice 需要一个字符串名来标识 slice,一个初始状态值,以及一个或多个 reducer 函数来定义状态如何被更新。一旦创建了一个 slice,我们可以导出生成的 Redux action 创建器和整个 slice 的 reducer 函数。
Redux 要求我们通过复制数据并更新副本来不可变地编写所有状态更新。然而,Redux Toolkit 的 createSlice
和 createReducer
API 内部使用 Immer,允许我们编写"变异"更新逻辑,这将变成正确的不可变更新。
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 允许 我们在 reducer 中编写 "变异" 逻辑。它
// 实际上并没有改变状态,因为它使用了 Immer 库,
// 该库检测到对 "草稿状态" 的更改,并根据这些更改生成一个全新的
// 不可变状态
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
},
})
// 为每个 case reducer 函数生成 action 创建器
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
将 Slice Reducers 添加到 Store
接下来,我们需要从 counter slice 导入 reducer 函数并将其添加到我们的 store。通过在 reducer
参数中定义一个字段,我们告诉 store 使用这个 slice reducer 函数来处理该状态的所有更新。
// 文件: features/counter/counterSlice.ts noEmit
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: {},
reducers: {},
})
export default counterSlice.reducer
// 文件: app/store.ts
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
// 从 store 本身推断 `RootState` 和 `AppDispatch` 类型
export type RootState = ReturnType<typeof store.getState>
// 推断的类型:{posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
在 React 组件中使用 Redux State 和 Actions
现在我们可以使用 React-Redux hooks 让 React 组件与 Redux store 交互。我们可以使用 useSelector
从 store 中读取数据,并使用 useDispatch
分发 actions。在 src/features/counter/Counter.js
文件中创建一个 <Counter>
组件,然后将该组件导入到 App.js
中并在 <App>
内部渲染它。
// 文件: features/counter/counterSlice.ts noEmit
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {},
decrement: (state) => {},
},
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer
// 文件: app/store.ts noEmit
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
// 文件: index.tsx noEmit
import React from 'react'
import ReactDOM from 'react-dom'
import { Counter } from './features/counter/Counter'
import { store } from './app/store'
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
)
// 文件: features/counter/Counter.tsx
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())}
>
增加
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
减少
</button>
</div>
</div>
)
}
现在,每当你点击 "增加" 和 "减少" 按钮时:
- 相应的 Redux action 将被分发到 store
- counter slice reducer 将看到 actions 并更新其状态
<Counter>
组件将从 store 中看到新的状态值并使用新的数据重新渲染自己
你学到了什么
这是一个如何使用 Redux Toolkit 和 React 设置和使用的简要概述。回顾一下细节:
- 使用
configureStore
创建一个 Redux storeconfigureStore
接受一个reducer
函数作为命名参数configureStore
自动使用良好的默认设置设置 store
- 为 React 应用程序组件提供 Redux store
- 在你的
<App />
周围放一个 React-Redux<Provider>
组件 - 将 Redux store 作为
<Provider store={store}>
传递
- 在你的
- 使用
createSlice
创建一个 Redux "slice" reducer- 使用字符串名称、初始状态和命名的 reducer 函数调用
createSlice
- Reducer 函数可以使用 Immer "变异"状态
- 导出生成的 slice reducer 和 action 创建器
- 使用字符串名称、初始状态和命名的 reducer 函数调用
- 在 React 组件中使用 React-Redux 的
useSelector/useDispatch
hooks- 使用
useSelector
hook 从 store 中读取数据 - 使用
useDispatch
hook 获取dispatch
函数,并根据需要分发 actions
- 使用
完整的 Counter App 示例
这里展示的 counter 示例应用也是
这是一个完整的 counter 应用作为一个运行的 CodeSandbox:
下一步是什么?
我们建议你阅读 Redux 核心文档中的 "Redux Essentials" 和 "Redux Fundamentals" 教程,这将给你一个完整的理解 Redux 如何工作,Redux Toolkit 是什么,以及如何正确使用它。