最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redux Toolkit 實(shí)戰(zhàn)小結(jié)

 更新時(shí)間:2026年03月24日 09:38:42   作者:Csvn  
Redux曾是React狀態(tài)管理的標(biāo)準(zhǔn)解決方案,但傳統(tǒng) Redux 的樣板代碼過多、配置復(fù)雜、異步處理繁瑣,Redux Toolkit(RTK)官方推出,旨在解決這些痛點(diǎn),下面就來詳細(xì)的介紹一下如何使用

引言

Redux 曾是 React 狀態(tài)管理的標(biāo)準(zhǔn)解決方案,但傳統(tǒng) Redux 的樣板代碼過多、配置復(fù)雜、異步處理繁瑣。Redux Toolkit(RTK)官方推出,旨在解決這些痛點(diǎn),成為現(xiàn)代 Redux 開發(fā)的標(biāo)準(zhǔn)方式。

一、為什么選擇 Redux Toolkit?

傳統(tǒng) Redux 的三大痛點(diǎn)

  1. 配置復(fù)雜:需要手動(dòng)配置 store、中間件、devtools
  2. 樣板代碼多:action types、action creators、reducers 分離
  3. 異步處理 麻煩:需要額外安裝 redux-thunk 或 redux-saga

RTK 的優(yōu)勢(shì)

特性傳統(tǒng) ReduxRedux Toolkit
Store 配置多行手動(dòng)配置configureStore 一行搞定
Action 定義手動(dòng)定義 type + creatorcreateSlice 自動(dòng)生成
不可變更新需要 spread 運(yùn)算符Immer 內(nèi)置,可直接修改
DevTools手動(dòng)配置自動(dòng)集成
TypeScript繁瑣的類型定義內(nèi)置類型支持

二、四步實(shí)戰(zhàn) Redux Toolkit

步驟 1:安裝與 Store 配置

npm install @reduxjs/toolkit react-redux
// src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
import userReducer from '../features/user/userSlice';
export const store = configureStore({
  reducer: {
    counter: counterReducer,
    user: userReducer,
  },
});
export default store;

configureStore 自動(dòng)幫你:

  • 配置 Redux DevTools
  • 設(shè)置 redux-thunk 中間件
  • 啟用 Immer 支持不可變更新

步驟 2:創(chuàng)建 Slice

// src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0,
    history: [],
  },
  reducers: {
    increment: (state) => {
      // Immer 允許直接修改 state
      state.value += 1;
      state.history.push(`+1 → ${state.value}`);
    },
    decrement: (state) => {
      state.value -= 1;
      state.history.push(`-1 → ${state.value}`);
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
      state.history.push(`+${action.payload} → ${state.value}`);
    },
    reset: (state) => {
      state.value = 0;
      state.history = [];
    },
  },
});
export const { increment, decrement, incrementByAmount, reset } = counterSlice.actions;
export default counterSlice.reducer;

createSlice 自動(dòng)生成:

  • Action types(counter/increment
  • Action creators(increment()
  • Reducer 函數(shù)

步驟 3:處理異步請(qǐng)求

// src/features/user/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
// 創(chuàng)建異步 thunk
export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId, { rejectWithValue }) => {
    try {
      const response = await axios.get(`/api/users/${userId}`);
      return response.data;
    } catch (error) {
      return rejectWithValue(error.response.data);
    }
  }
);
const userSlice = createSlice({
  name: 'user',
  initialState: {
    data: null,
    loading: false,
    error: null,
  },
  reducers: {
    clearUser: (state) => {
      state.data = null;
      state.error = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload;
      });
  },
});
export const { clearUser } = userSlice.actions;
export default userSlice.reducer;

createAsyncThunk 自動(dòng)生成三種狀態(tài):

  • pending:請(qǐng)求中
  • fulfilled:請(qǐng)求成功
  • rejected:請(qǐng)求失敗

步驟 4:React 組件中使用

// src/components/Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount, reset } from '../features/counter/counterSlice';
function Counter() {
  const count = useSelector((state) => state.counter.value);
  const history = useSelector((state) => state.counter.history);
  const dispatch = useDispatch();
  return (
    <div className="counter">
      <h2>計(jì)數(shù)器:{count}</h2>
      <div className="buttons">
        <button onClick={() => dispatch(decrement())}>-</button>
        <button onClick={() => dispatch(increment())}>+</button>
        <button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
        <button onClick={() => dispatch(reset())}>重置</button>
      </div>
      {history.length > 0 && (
        <div className="history">
          <h3>操作歷史:</h3>
          <ul>
            {history.map((item, index) => (
              <li key={index}>{item}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}
export default Counter;
// src/components/UserProfile.jsx
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchUser, clearUser } from '../features/user/userSlice';
function UserProfile({ userId }) {
  const dispatch = useDispatch();
  const { data, loading, error } = useSelector((state) => state.user);
  useEffect(() => {
    dispatch(fetchUser(userId));
  }, [userId, dispatch]);
  if (loading) return <div>加載中...</div>;
  if (error) return <div>錯(cuò)誤:{error}</div>;
  if (!data) return null;
  return (
    <div className="user-profile">
      <h2>{data.name}</h2>
      <p>郵箱:{data.email}</p>
      <button onClick={() => dispatch(clearUser())}>清除</button>
    </div>
  );
}
export default UserProfile;

三、項(xiàng)目結(jié)構(gòu)組織

src/
├── app/
│   └── store.js          # Store 配置
├── features/
│   ├── counter/
│   │   ├── counterSlice.js
│   │   └── Counter.jsx
│   └── user/
│       ├── userSlice.js
│       └── UserProfile.jsx
├── components/            # 通用組件
└── index.js              # 入口文件
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    <App />
  </Provider>
);

四、最佳實(shí)踐

1. 使用 Typed Hooks(TypeScript 項(xiàng)目)

// src/app/hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';
// 在整個(gè)應(yīng)用中使用這些 hooks,而非默認(rèn)的 useDispatch/useSelector
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

2. Slice 文件組織

  • 每個(gè)功能模塊一個(gè) slice
  • 相關(guān)的組件和 slice 放在同一目錄
  • 使用 export 統(tǒng)一導(dǎo)出 actions 和 reducer

3. 避免的常見錯(cuò)誤

錯(cuò)誤做法正確做法
直接修改 state 外部只在 reducer 內(nèi)修改
在 slice 中發(fā)異步請(qǐng)求使用 createAsyncThunk
過多全局狀態(tài)局部狀態(tài)用 useState
忽略 extraReducers正確處理異步狀態(tài)

總結(jié)

Redux Toolkit 讓 Redux 開發(fā)變得簡(jiǎn)單高效:

  1. configureStore - 一鍵配置 store
  2. createSlice - 自動(dòng)生成 action + reducer
  3. createAsyncThunk - 優(yōu)雅處理異步
  4. Immer 內(nèi)置 - 直接修改 state 無副作用

選型建議:

  • 小型應(yīng)用 → Context 或 Zustand
  • 中大型應(yīng)用 → Redux Toolkit
  • 需要時(shí)間旅行調(diào)試 → Redux Toolkit

到此這篇關(guān)于Redux Toolkit 實(shí)戰(zhàn)小結(jié)的文章就介紹到這了,更多相關(guān)Redux Toolkit 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 回顧Javascript React基礎(chǔ)

    回顧Javascript React基礎(chǔ)

    這篇文章主要介紹了Javascript React基礎(chǔ),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的同學(xué)可以參考一下
    2019-06-06
  • 如何在React中通過URL預(yù)覽Excel文件

    如何在React中通過URL預(yù)覽Excel文件

    這篇文章主要為大家詳細(xì)介紹了如何在React中通過URL預(yù)覽Excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • React Native可復(fù)用 UI分離布局組件和狀態(tài)組件技巧

    React Native可復(fù)用 UI分離布局組件和狀態(tài)組件技巧

    這篇文章主要為大家介紹了React Native可復(fù)用 UI分離布局組件和狀態(tài)組件使用技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 關(guān)于React狀態(tài)管理的三個(gè)規(guī)則總結(jié)

    關(guān)于React狀態(tài)管理的三個(gè)規(guī)則總結(jié)

    隨著 JavaScript 單頁應(yīng)用開發(fā)日趨復(fù)雜,JavaScript 需要管理比任何時(shí)候都要多的 state (狀態(tài)),這篇文章主要給大家介紹了關(guān)于React狀態(tài)管理的三個(gè)規(guī)則,需要的朋友可以參考下
    2021-07-07
  • 在React中this容易遇到的問題詳解

    在React中this容易遇到的問題詳解

    這篇文章主要介紹了在React中this容易遇到的問題總結(jié),文中有詳細(xì)的示例代碼,希望對(duì)大家有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • react路由跳轉(zhuǎn)傳參刷新頁面后參數(shù)丟失的解決

    react路由跳轉(zhuǎn)傳參刷新頁面后參數(shù)丟失的解決

    這篇文章主要介紹了react路由跳轉(zhuǎn)傳參刷新頁面后參數(shù)丟失的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • react實(shí)現(xiàn)動(dòng)態(tài)選擇框

    react實(shí)現(xiàn)動(dòng)態(tài)選擇框

    這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)動(dòng)態(tài)選擇框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React.InputHTMLAttributes實(shí)踐和注意事項(xiàng)

    React.InputHTMLAttributes實(shí)踐和注意事項(xiàng)

    文章討論了如何在封裝組件中使用React.InputHTMLAttributes,以及如何通過 {...inputProps} 動(dòng)態(tài)傳遞屬性,最后,文章總結(jié)了使用React.InputHTMLAttributes的最佳實(shí)踐和注意事項(xiàng),感興趣的朋友一起看看吧
    2024-11-11
  • React中的Context應(yīng)用場(chǎng)景分析

    React中的Context應(yīng)用場(chǎng)景分析

    這篇文章主要介紹了React中的Context應(yīng)用場(chǎng)景分析,Context 提供了一種在組件之間共享數(shù)據(jù)的方式,而不必顯式地通過組件樹的逐層傳遞 props,通過實(shí)例代碼給大家介紹使用步驟,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • react-router-dom6(對(duì)比?router5)快速入門指南

    react-router-dom6(對(duì)比?router5)快速入門指南

    這篇文章主要介紹了快速上手react-router-dom6(對(duì)比?router5),通過本文學(xué)習(xí)最新的react-router-dom?v6版本的路由知識(shí),并且會(huì)與v5老版本進(jìn)行一些對(duì)比,需要的朋友可以參考下
    2022-08-08

最新評(píng)論

永城市| 城市| 绥棱县| 保德县| 鱼台县| 新巴尔虎右旗| 鹿泉市| 青冈县| 定南县| 冷水江市| 高台县| 连江县| 陆川县| 高雄县| 常山县| 德州市| 南郑县| 石泉县| 景东| 闵行区| 新绛县| 彭水| 河津市| 甘谷县| 馆陶县| 楚雄市| 滨州市| 泽州县| 凯里市| 清丰县| 江陵县| 龙口市| 北京市| 沙坪坝区| 颍上县| 合阳县| 五莲县| 新余市| 怀柔区| 陆良县| 阿尔山市|