跳到主要内容

 

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 中,但这些模式可以适应你正在使用的任何项目或文件夹设置。

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,并导出它:

app/store.js
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 传递:

index.js
// 文件: 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 的 createSlicecreateReducer API 内部使用 Immer,允许我们编写"变异"更新逻辑,这将变成正确的不可变更新

features/counter/counterSlice.js
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 函数来处理该状态的所有更新。

app/store.js
// 文件: 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/Counter.js
// 文件: 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 store
    • configureStore 接受一个 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 创建器
  • 在 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 是什么,以及如何正确使用它。