Redux-Toolkit 学习笔记:简化 Redux 的终极方案
1. Redux-Toolkit 简介
Redux-Toolkit (RTK) 是 Redux 官方推荐的简化 Redux 开发的工具集,它提供了一系列工具来简化常见的 Redux 使用模式,包括配置 store、创建 reducer 和 actions 等。
主要优点
- 简化 Redux 配置
- 减少样板代码
- 内置最佳实践
- 集成 Immer 和 Redux-Thunk
2. 核心 API
2.1 configureStore
替代传统的 createStore
,提供简化的配置方式:
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: {
// 添加你的 reducers 这里
posts: postsReducer,
comments: commentsReducer,
users: usersReducer,
},
// 可选配置
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
devTools: process.env.NODE_ENV !== 'production',
preloadedState: initialState,
});
2.2 createSlice
自动生成 action creators 和 action types,简化 reducer 创建:
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
incrementByAmount: (state, action) => state + action.payload,
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
2.3 createAsyncThunk
简化异步操作处理:
import { createAsyncThunk } from '@reduxjs/toolkit';
export const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId);
return response.data;
}
);
2.4 createEntityAdapter
提供标准化的数据存储和操作:
import { createEntityAdapter } from '@reduxjs/toolkit';
const usersAdapter = createEntityAdapter({
selectId: (user) => user.id,
sortComparer: (a, b) => a.name.localeCompare(b.name),
});
3. 实际应用示例
3.1 创建 Store
// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
import usersReducer from '../features/users/usersSlice';
export default configureStore({
reducer: {
counter: counterReducer,
users: usersReducer,
},
});
3.2 创建 Slice
// postsSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchPosts } from './api';
export const getPosts = createAsyncThunk('posts/getPosts', async () => {
const response = await fetchPosts();
return response.data;
});
const postsSlice = createSlice({
name: 'posts',
initialState: {
items: [],
status: 'idle',
error: null,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getPosts.pending, (state) => {
state.status = 'loading';
})
.addCase(getPosts.fulfilled, (state, action) => {
state.status = 'succeeded';
state.items = action.payload;
})
.addCase(getPosts.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});
export default postsSlice.reducer;
3.3 在组件中使用
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getPosts } from './postsSlice';
function PostsList() {
const dispatch = useDispatch();
const posts = useSelector((state) => state.posts.items);
const status = useSelector((state) => state.posts.status);
const error = useSelector((state) => state.posts.error);
useEffect(() => {
if (status === 'idle') {
dispatch(getPosts());
}
}, [status, dispatch]);
if (status === 'loading') return <div>Loading...</div>;
if (status === 'failed') return <div>Error: {error}</div>;
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
4. 最佳实践
- 使用 RTK Query 处理数据获取:对于数据获取和缓存,优先考虑使用 RTK Query
- 按功能组织代码:将相关 slice、actions 和 selectors 放在同一文件中
- 使用 Immer 进行不可变更新:RTK 内置了 Immer,可以直接"修改"state
- 避免在 reducer 中执行副作用:将异步逻辑放在 thunks 中
- 使用 TypeScript:RTK 对 TypeScript 有很好的支持
5. RTK Query
RTK Query 是 Redux Toolkit 中包含的数据获取和缓存解决方案:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
endpoints: (builder) => ({
getPosts: builder.query({
query: () => '/posts',
}),
addNewPost: builder.mutation({
query: (post) => ({
url: '/posts',
method: 'POST',
body: post,
}),
}),
}),
});
export const { useGetPostsQuery, useAddNewPostMutation } = apiSlice;
6. 总结
Redux Toolkit 极大地简化了 Redux 的使用,减少了样板代码,内置了最佳实践,使得 Redux 更加易于使用和维护。对于新项目,强烈建议使用 Redux Toolkit 而不是传统的 Redux。