在使用 Redux Toolkit 时,通常不需要手动调用 createStore
,因为 Redux Toolkit 提供了一个更高级的函数 configureStore
,它是 createStore
的封装版本,并且默认配置了很多常用功能,比如 Redux DevTools 和中间件(如 redux-thunk
)。
1. 为什么不用 createStore
?
Redux Toolkit 的目标是简化 Redux 的开发流程,减少样板代码和配置工作。configureStore
是 Redux Toolkit 提供的一个简化工具,它可以自动完成以下工作:
- 默认启用
redux-thunk
中间件(用于处理异步操作)。 - 自动启用 Redux DevTools,方便调试。
- 支持更简单的 reducer 合并(不需要手动调用
combineReducers
)。 - 更加直观的配置方式。
而 createStore
是 Redux 的原始方法,需要手动配置这些功能,代码会比较冗长。
2. configureStore
的使用
configureStore
是 Redux Toolkit 的推荐方式。它和 createAsyncThunk
、createSlice
配合使用时,可以完全替代传统的 createStore
。
示例:
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';
import productReducer from './productSlice';
// 使用 configureStore 配置 store
const store = configureStore({
reducer: {
user: userReducer, // 注册 userSlice 的 reducer
product: productReducer, // 注册 productSlice 的 reducer
},
});
export default store;
参数解释:
-
reducer
:- 是一个对象,用于注册多个 slice 的 reducer。
- Redux Toolkit 会自动调用
combineReducers
,将多个 reducer 合并成一个。
-
middleware
(可选):- 用于自定义中间件(默认已经包含
redux-thunk
)。 - 如果需要添加额外的中间件,可以在这里配置。
- 用于自定义中间件(默认已经包含
-
devTools
(可选):- 默认启用 Redux DevTools,如果需要关闭或自定义,可以通过该选项配置。
3. 如果不用 configureStore
,仍然可以用 createStore
吗?
当然可以,但这样会失去 Redux Toolkit 的便利性,需要手动配置很多内容。
示例:手动使用 createStore
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import userReducer from './userSlice';
import productReducer from './productSlice';
// 手动合并 reducers
const rootReducer = combineReducers({
user: userReducer,
product: productReducer,
});
// 手动创建 store
const store = createStore(
rootReducer,
applyMiddleware(thunk) // 手动添加 redux-thunk
);
export default store;
缺点:
- 需要手动调用
combineReducers
。 - 需要手动添加中间件(例如
redux-thunk
)。 - 不会自动启用 Redux DevTools(需要手动配置)。
4. configureStore
的优势
自动配置中间件
configureStore
默认包含了 redux-thunk
,而且还会自动检查 reducer 中是否有不可变操作(启用 redux-immutable-state-invariant
)。
自动启用 Redux DevTools
无需手动配置,开发环境下会自动启用 Redux DevTools,方便调试。
更少样板代码
不需要手动调用 combineReducers
,直接通过 reducer
参数注册多个 slice。
示例对比:
-
使用
configureStore
:import { configureStore } from '@reduxjs/toolkit'; import userReducer from './userSlice'; const store = configureStore({ reducer: { user: userReducer, }, }); export default store;
-
使用
createStore
:import { createStore, applyMiddleware, combineReducers } from 'redux'; import thunk from 'redux-thunk'; import userReducer from './userSlice'; const rootReducer = combineReducers({ user: userReducer, }); const store = createStore( rootReducer, applyMiddleware(thunk) ); export default store;
可以看到,configureStore
的代码更加简洁。
5. 总结:Redux Toolkit 是否取代了 createStore
?
-
推荐使用
configureStore
:- 如果你使用 Redux Toolkit(包括
createAsyncThunk
和createSlice
),建议使用configureStore
,它可以完全取代createStore
,并且提供了很多默认的优化。
- 如果你使用 Redux Toolkit(包括
-
仍然可以使用
createStore
:- 如果你在一个老的 Redux 项目中,或者有非常特殊的需求,可以继续使用
createStore
。 - 但是,在大多数情况下,
configureStore
是更好的选择。
- 如果你在一个老的 Redux 项目中,或者有非常特殊的需求,可以继续使用
6. 完整的 Redux Toolkit 示例
定义一个 userSlice
:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 异步操作
export const fetchUser = createAsyncThunk('user/fetchUser', async (userId) => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
// 定义 slice
const userSlice = createSlice({
name: 'user',
initialState: { user: null, status: 'idle', error: null },
reducers: {
clearUser(state) {
state.user = null;
},
},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded';
state.user = action.payload;
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});
// 导出同步 action
export const { clearUser } = userSlice.actions;
// 导出 reducer
export default userSlice.reducer;
配置 store
:
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';
const store = configureStore({
reducer: {
user: userReducer,
},
});
export default store;
使用 store
:
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUser, clearUser } from './userSlice';
function App() {
const dispatch = useDispatch();
const user = useSelector((state) => state.user.user);
const status = useSelector((state) => state.user.status);
return (
<div>
<button onClick={() => dispatch(fetchUser(1))}>Fetch User</button>
<button onClick={() => dispatch(clearUser())}>Clear User</button>
{status === 'loading' && <p>Loading...</p>}
{status === 'succeeded' && <p>User: {user.name}</p>}
{status === 'failed' && <p>Error: {user.error}</p>}
</div>
);
}
export default App;
通过以上代码,你可以看到,使用 Redux Toolkit 的 configureStore
,整个流程更加清晰和简洁。