Redux Toolkit 快速上手
FreeGuideOnline
14阅读
2026-07-13
bash npm create vite@latest redux-toolkit-demo -- --template react cd redux-toolkit-demo npm install
### 安装 Redux Toolkit 和 React-Redux
```bash
npm install @reduxjs/toolkit react-redux
@reduxjs/toolkit:包含核心工具函数。react-redux:用于在 React 中连接 Redux Store。
核心概念与第一个 Slice
Redux Toolkit 的核心是 Slice。一个 Slice 将某个功能模块的 state、reducer 和 actions 封装在一起。
创建计数器 Slice
在 src 目录下新建 store 文件夹,然后创建 counterSlice.js:
// src/store/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter', // slice 名称,作为 action type 前缀
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
// 直接修改 state,Immer 会处理不可变更新
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// 导出自动生成的 action creators
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// 导出 reducer
export default counterSlice.reducer;
解析:
createSlice需要name、initialState和reducers字段。reducers中的每个函数可以接收state和action,我们直接操作state,无需返回新对象。action.payload自动携带调用时传入的参数。createSlice自动生成对应名称的 action types,如counter/increment。
创建并配置 Store
Store 是整个应用的单一状态树。使用 configureStore 可以一行代码创建 store,并自动合并多个 reducer。
创建 src/store/index.js:
// src/store/index.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer, // 将 counter reducer 挂载到 state.counter
},
});
configureStore默认启用 Redux DevTools 扩展和redux-thunk中间件。- 如果有多个 Slice,只需在
reducer对象中继续添加即可。
在 React 中连接 Store
使用 react-redux 提供的 <Provider> 包裹根组件,并将 store 传入。
修改 src/main.jsx:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './store';
import './index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
在组件中使用 State 和 Dispatch
react-redux 提供了两个核心 Hook:useSelector 用于读取状态,useDispatch 用于派发 action。
修改 src/App.jsx:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './store/counterSlice';
function App() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div style={{ textAlign: 'center', marginTop: '2rem' }}>
<h1>计数器:{count}</h1>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
<button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
</div>
);
}
export default App;
说明:
useSelector接收一个函数,从整个 state 中挑选需要的数据,并自动订阅 store 的变化。useDispatch返回 store 的dispatch方法,用于触发 action creators 生成的 action。
处理异步逻辑:createAsyncThunk
真实的项目中,数据往往来自 API 调用。Redux Toolkit 提供了 createAsyncThunk 来优雅地处理异步请求,并自动生成 pending、fulfilled、rejected 三种 action。
示例:获取用户列表
假设我们有一个 JSONPlaceholder 接口。在 store 下新建 userSlice.js:
// src/store/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 创建异步 thunk
export const fetchUsers = createAsyncThunk('users/fetchUsers', async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
return response.json(); // 自动成为 fulfilled action 的 payload
});
const userSlice = createSlice({
name: 'users',
initialState: {
users: [],
status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed'
error: null,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUsers.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchUsers.fulfilled, (state, action) => {
state.status = 'succeeded';
state.users = action.payload;
})
.addCase(fetchUsers.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});
export default userSlice.reducer;
然后将 userReducer 添加到 store:
// store/index.js
import userReducer from './userSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
users: userReducer, // 新增
},
});
在组件中使用:
import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchUsers } from './store/userSlice';
function Users() {
const dispatch = useDispatch();
const { users, status, error } = useSelector((state) => state.users);
useEffect(() => {
if (status === 'idle') {
dispatch(fetchUsers());
}
}, [status, dispatch]);
if (status === 'loading') return <p>加载中...</p>;
if (status === 'failed') return <p>错误: {error}</p>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default Users;
关键点:
createAsyncThunk第一个参数是 action type 前缀,第二个是异步函数。extraReducers通过 builder 模式处理 thunk 的生命周期 action。- 通过
status字段可以轻松实现加载状态和错误展示,无需额外 boolean。
使用 Immer 更新嵌套对象
Redux Toolkit 内置 Immer,允许我们以可变的方式更新深层嵌套的 state,但前提是不要混用可变与不可变操作。以下是一个嵌套更新的示例:
reducers: {
updateAddress: (state, action) => {
// 直接修改深层属性,Immer 会转换为不可变更新
state.user.address.city = action.payload;
},
}