面試官:Redux-Toolkit 是什么,你知道嗎?
Redux Toolkit(RTK)是 Redux 官方推薦的 狀態(tài)管理庫(kù),它簡(jiǎn)化了 Redux 的開(kāi)發(fā)流程,使 Redux 更簡(jiǎn)單、更高效。
?? 為什么需要 Redux Toolkit?
- 簡(jiǎn)化 Redux 代碼(減少 boilerplate 代碼)
- 自動(dòng)優(yōu)化狀態(tài)更新(內(nèi)置 Immer.js,支持 可變寫(xiě)法)
- 內(nèi)置異步處理(Redux Thunk)
- 性能優(yōu)化(自動(dòng) reducer 組合,支持 lazy loading)
?? Redux Toolkit vs 傳統(tǒng) Redux
?? 特性 | 傳統(tǒng) Redux | Redux Toolkit |
Reducer 書(shū)寫(xiě) | 需要手寫(xiě) | 直接用 |
異步處理 | 需手寫(xiě) | 內(nèi)置 |
狀態(tài)更新 | 需手寫(xiě)不可變數(shù)據(jù)更新 | 支持可變寫(xiě)法 ( |
Store 配置 | 需手寫(xiě) |
自動(dòng)配置 |
默認(rèn)優(yōu)化 | 需手動(dòng)優(yōu)化性能 | 自動(dòng)優(yōu)化 ( |
?? Redux Toolkit 基本使用
1?? 安裝 Redux Toolkit
npm install @reduxjs/toolkit react-redux
2?? 創(chuàng)建 store
?? 使用 configureStore 代替 createStore:
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
? configureStore 自動(dòng)整合 Reducer、Middleware,不需要手動(dòng)配置。
3?? 創(chuàng)建 slice(Reducer + Action)
?? 傳統(tǒng) Redux 需要寫(xiě) action + reducer,而 createSlice 一步搞定!
import { createSlice } from "@reduxjs/toolkit";
const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; }, // ? 直接修改 state(內(nèi)部使用 `Immer.js`)
decrement: (state) => { state.value -= 1; },
addByAmount: (state, action) => { state.value += action.payload; },
},
});
// 導(dǎo)出 Actions
export const { increment, decrement, addByAmount } = counterSlice.actions;
// 導(dǎo)出 Reducer
export default counterSlice.reducer;
? 優(yōu)勢(shì):
- **自動(dòng)生成 action**(無(wú)需手寫(xiě) type)
- 支持可變寫(xiě)法(內(nèi)部使用 Immer.js)
4?? 組件中使用 Redux
?? 使用 useSelector 讀取 Redux 狀態(tài)
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement, addByAmount } from "./counterSlice";
function Counter() {
const count = useSelector(state => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>+1</button>
<button onClick={() => dispatch(decrement())}>-1</button>
<button onClick={() => dispatch(addByAmount(5))}>+5</button>
</div>
);
}
export default Counter;
? 簡(jiǎn)潔易懂!不需要 connect,直接 useSelector 讀取狀態(tài),dispatch 觸發(fā)更新。
?? Redux Toolkit 處理異步請(qǐng)求
?? 使用 createAsyncThunk 處理異步請(qǐng)求
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
// 創(chuàng)建異步 Action(自動(dòng)處理 `pending`, `fulfilled`, `rejected`)
export const fetchData = createAsyncThunk("data/fetchData", async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
return await response.json();
});
const dataSlice = createSlice({
name: "data",
initialState: { item: null, loading: false, error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchData.pending, (state) => { state.loading = true; })
.addCase(fetchData.fulfilled, (state, action) => {
state.loading = false;
state.item = action.payload;
})
.addCase(fetchData.rejected, (state) => { state.loading = false; });
},
});
export default dataSlice.reducer;
?? 組件中使用異步 Action
import { useSelector, useDispatch } from "react-redux";
import { fetchData } from "./dataSlice";
function DataComponent() {
const { item, loading } = useSelector(state => state.data);
const dispatch = useDispatch();
return (
<div>
{loading ? <p>Loading...</p> : <p>Data: {item?.title}</p>}
<button onClick={() => dispatch(fetchData())}>Fetch Data</button>
</div>
);
}
? 優(yōu)勢(shì):
- createAsyncThunk 自動(dòng)管理 loading 狀態(tài)
- 不需要手寫(xiě) redux-thunk
- extraReducers 處理異步狀態(tài),代碼更清晰
?? Redux Toolkit 還提供的高級(jí)功能
1?? RTK Query(數(shù)據(jù)請(qǐng)求 & 緩存)
?? 自動(dòng)管理 API 數(shù)據(jù)請(qǐng)求、緩存、狀態(tài)
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
// 創(chuàng)建 API Slice
export const postApi = createApi({
reducerPath: "postApi",
baseQuery: fetchBaseQuery({ baseUrl: "https://jsonplaceholder.typicode.com" }),
endpoints: (builder) => ({
getPosts: builder.query({ query: () => "/posts" }),
}),
});
// 自動(dòng)生成 Hooks
export const { useGetPostsQuery } = postApi;
?? 組件中直接調(diào)用 API
const { data, error, isLoading } = useGetPostsQuery();
? 優(yōu)勢(shì):
- 自動(dòng)緩存數(shù)據(jù),避免重復(fù)請(qǐng)求
- 支持 realtime polling(輪詢)
- 支持 WebSocket 訂閱
?? 總結(jié)
Redux Toolkit 優(yōu)勢(shì) | ? 優(yōu)化點(diǎn) |
簡(jiǎn)化 Redux 代碼 |
代替 |
自動(dòng)優(yōu)化 |
自動(dòng)組合 |
支持可變寫(xiě)法 | 內(nèi)置 |
內(nèi)置異步處理 |
代替 |
支持 API 緩存 |
自動(dòng)緩存 API 請(qǐng)求數(shù)據(jù) |
提高性能 |
+ 自動(dòng) |
?? Redux Toolkit 是 Redux 的現(xiàn)代化解決方案,推薦用于 React + Redux 開(kāi)發(fā)!