輕松搞定 reduxjs/toolkit

1. 前言

  1. toolkit
  2. 最近創(chuàng)建 react腳手架項(xiàng)目的時(shí)候發(fā)現(xiàn), 默認(rèn)安裝的 react版本已經(jīng)變?yōu)?code>18X了,
  3. 原來的項(xiàng)目換成18X也能運(yùn)行,但是 redux中的createStore出現(xiàn)了橫崗也就是被廢棄了
  4. 那就看看 新出的啥東西代替了createStore,體驗(yàn)下好用不

2. 是什么 what

Redux Toolkit包旨在成為編寫Redux邏輯的標(biāo)準(zhǔn)方式。它最初的創(chuàng)建是為了幫助解決關(guān)于 Redux 的三個(gè)常見問題:

  1. 配置 Redux 存儲(chǔ)太復(fù)雜了
  2. 我必須添加很多包才能讓 Redux 做任何有用的事情
  3. Redux 需要太多樣板代碼

3. 環(huán)境安裝

注意不要拼錯(cuò) @reduxjs/toolkit

npm install @reduxjs/toolkit react-redux
yarn add @reduxjs/toolkit react-redux

react-redux 也需要單獨(dú)安裝


4. configureStore

  1. configureStore替代 createStore
  2. 配置簡(jiǎn)單,設(shè)置默認(rèn)值也方便
  3. src/store/index.js
// 引入
import {configureStore} from '@reduxjs/toolkit'
import counterSlice from "../pages/basic/counterSlice"
import mySlice from "../pages/mySlice"

export default configureStore({
  reducer:{
    rootCounter:counterSlice,
    rootMy:mySlice
  }
})
  1. 這里 reduer直接合并成一個(gè)唯一的 根root了
  2. 原有的combineReducers這個(gè)合并函數(shù)就用不到了
  3. 注意自己配置的 reducer的 key值 和 對(duì)應(yīng)的value值
  4. 我這里把單獨(dú)的 reducer 放到和頁(yè)面同級(jí)了,這個(gè)根據(jù)自己的習(xí)慣,放到 store下面新建目錄存放所有的reducer也行

5. 根組件配置 store

  1. 入口index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import store from './store'
import {Provider} from 'react-redux'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
   <Provider store={store}>
         <App />
    </Provider>
  </React.StrictMode>
);


6. createSlice reducer編寫

1. 創(chuàng)建slice

使用createSlice方法創(chuàng)建一個(gè)slice晓褪。每一個(gè)slice里面包含了reducer和actions貌夕,可以實(shí)現(xiàn)模塊化的封裝。
所有的相關(guān)操作都獨(dú)立在一個(gè)文件中完成貌踏。

2. 關(guān)鍵屬性:

  1. name
    命名空間,可以自動(dòng)的把每一個(gè)action進(jìn)行獨(dú)立,解決了action的type出現(xiàn)同名的文件蚀之。在使用的時(shí)候默認(rèn)會(huì)把使用name/actionName
  1. initialState
    state數(shù)據(jù)的初始值

3.reducers
定義的action。由于內(nèi)置了immutable插件捷泞,可以直接使用賦值的方式進(jìn)行數(shù)據(jù)的改變足删,不需要每一次都返回一個(gè)新的state數(shù)據(jù)。

import { createSlice } from "@reduxjs/toolkit";
const initialState = {
  counter: 100,
  user: {
    name: "yzs",
    job: "全棧",
  },
};
export const counterSlice = createSlice({
  name: "counterSpace", // 命名空間锁右,在調(diào)用action的時(shí)候會(huì)默認(rèn)的設(shè)置為action的前綴,保證唯一.不重名
  initialState,
  reducers: {
// reducer函數(shù) state當(dāng)前組件的數(shù)據(jù) 
//第二個(gè)參數(shù)為{payload:{},type:"""} 想想就寫法或者vuex
    increment(state) {
      state.counter += 100;
    },
    decrement(state, actions) {
      // actions == {payload:{},type:"""}
      console.log("decrement---actions", actions);
      state.counter -= actions.payload;
    },
    updateUser(state, { payload }) {
      console.log("updateUser-------payload", payload);
// 引用類型 注意 賦值的寫法
      state.user = {
        ...state.user,
        ...payload,
      };
    },
  },
});
export const { increment, decrement, updateUser } = counterSlice.actions;
export const selectCount = (state) => state.rootCounter.counter;
export const selectUser = (state) => state.rootCounter.user;

export default counterSlice.reducer;

3. 導(dǎo)出

  1. counterSlice.actions 導(dǎo)出所有的修改函數(shù)方便頁(yè)面使用
  2. counterSlice.reducer 導(dǎo)出reducer在 store里面使用

4. 具體reducer 函數(shù)的參數(shù)

參數(shù)1: 當(dāng)前slice的state數(shù)據(jù)
參數(shù)2: 對(duì)象{type:"",payload:傳參}

type:counterSpace/decrement
type就是之前的 actions用switc/case來匹配很麻煩,現(xiàn)在簡(jiǎn)潔了
type構(gòu)成 slice的 name命名空間/具體的修改函數(shù)

payload 要和傳的時(shí)候保持一致


7. 頁(yè)面使用

7.1. useSelector()

  1. 返回指定的 state
// 這樣寫太長(zhǎng)了 麻煩
 const counter = useSelector(state=>state.rootCouter.counter);
  1. rootCouter這個(gè)key 來源于 根 store里面配置的reducer
  2. 這樣寫太長(zhǎng)了 麻煩
  3. 在這個(gè) slice里面我做了統(tǒng)一處理
export const selectCount = (state) => state.rootCounter.counter;
export const selectUser = (state) => state.rootCounter.user;
  1. 頁(yè)面使用
import { useSelector, useDispatch } from "react-redux";
import {
  increment,
  decrement,
  updateUser,
  selectCount,
  selectUser,
} from "./normalSlice";
export default function Counter() {
  const dispatch = useDispatch();

  // let counter = useSelector(state=>state.rootCouter.counter)
  const counter = useSelector(selectCount);
  console.log("頁(yè)面---counter:", counter);
  const user = useSelector(selectUser);

// 這樣可以直接解構(gòu)出當(dāng)前 slice所有的 state
// 具體用哪種 看自己心情
 const { counter } = useSelector((state) => state.rootCouter);

return ( <div> 布局看下面 </div>)

7.2 useDispatch()

const dispatch = useDispatch(); 修改函數(shù)

  return (
    <div>
      <h1>reduxjs/toolkit 基礎(chǔ)用法</h1>
      <hr />
      <button onClick={() => dispatch(increment())}>+</button>
      <span>{counter}</span>
      <button onClick={() => dispatch(decrement(666))}>-</button>
      <hr />
      <h1>姓名:{user.name} ---職業(yè):{user.job}</h1>
      <button onClick={()=>{dispatch(updateUser({name:'Michael'}))}}>改名</button>
      <button onClick={()=>{
        dispatch(updateUser({job:'自由職業(yè)者'}))}
        }>轉(zhuǎn)行</button>
    </div>
  );
}
  1. payload傳參和 reducer保持一致
  2. 引用類型的 修改注意

8. 異步 createAsyncThunk()

  1. 接受一個(gè)動(dòng)作類型字符串和一個(gè)返回Promise函數(shù)失受,并生成一個(gè)pending/fulfilled/rejected基于該Promise分派動(dòng)作類型的 thunk
  2. 用 fetch請(qǐng)求模擬一個(gè)異步
    3.createAsyncThunk("counterSpace/getList",()=>{})
  3. 參數(shù)1: slice的name/命名空間/函數(shù)名
// return 不要忘記
export const getList = ( ) => {
return fetch("https://.XX.cn/api/news").then(res=>res.json());
};
export const  getListAsync =  createAsyncThunk("counterSpace/getList",async()=>{
  const res = await getList()
  return res// 此處的返回結(jié)果會(huì)在 .fulfilled中作為payload的值
});


9.extraReducers

  1. 異步函數(shù)配置
createSlice({
    name: "counterSpace",
    initialState,
    reducers:{},
    extraReducers: (builder) => {
    builder
      .addCase(getListAsync.pending, (state) => {
         console.log("pending",state);
      })
      .addCase(getListAsync.rejected, (state, err) => {
        console.log("rejected 失敗",err);

      })
      .addCase(getListAsync.fulfilled, (state, action) => {
         console.log("fulfilled 成功",state);
        console.log("fulfilled action",action);

        state.list = action.payload
      });
  },
});
  1. 這個(gè)配置基本就是套路
  2. 只需要把函數(shù)名字改為通過createAsyncThunk()創(chuàng)建的函數(shù)名
  3. 根據(jù)自己的業(yè)務(wù)場(chǎng)景 寫賦值邏輯就行

10. 頁(yè)面使用異步函數(shù)

<button onClick={()=>dispatch(getListAsync('異步模擬'))}>異步</button>
      <ul>
        {
          listData.map((news)=>{
            return <li key={news.id}>{news.title}</li>
          })
        }
      </ul>
  1. 效果圖
    1.png
  2. 也可以傳參數(shù)

參考資料

redux-toolkit


初心

我所有的文章都只是基于入門,初步的了解咏瑟;是自己的知識(shí)體系梳理,如有錯(cuò)誤,道友們一起溝通交流;
如果能幫助到有緣人,非常的榮幸,一切為了部落的崛起;
共勉
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贱纠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子响蕴,更是在濱河造成了極大的恐慌谆焊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浦夷,死亡現(xiàn)場(chǎng)離奇詭異辖试,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)劈狐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門罐孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肥缔,你說我怎么就攤上這事莲兢。” “怎么了续膳?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵改艇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我坟岔,道長(zhǎng)谒兄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任社付,我火速辦了婚禮承疲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸥咖。我一直安慰自己燕鸽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布啼辣。 她就那樣靜靜地躺著啊研,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悲伶,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音住涉,去河邊找鬼麸锉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舆声,可吹牛的內(nèi)容都是我干的花沉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼媳握,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼碱屁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛾找,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤娩脾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后打毛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柿赊,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年幻枉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碰声。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡熬甫,死狀恐怖胰挑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椿肩,我是刑警寧澤瞻颂,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站郑象,受9級(jí)特大地震影響蘸朋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扣唱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一藕坯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧噪沙,春花似錦炼彪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至局义,卻和暖如春喜爷,著一層夾襖步出監(jiān)牢的瞬間冗疮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工檩帐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留术幔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓湃密,卻偏偏與公主長(zhǎng)得像诅挑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泛源,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 序言 在平時(shí)寫業(yè)務(wù)代碼的時(shí)候拔妥,使用redux經(jīng)常會(huì)遇到一些問題: 狀態(tài)管理代碼分散在action,constant...
    星月西閱讀 6,991評(píng)論 0 1
  • Redux 教程 Redux 是 JavaScript 狀態(tài)容器达箍,提供可預(yù)測(cè)化的狀態(tài)管理没龙。 (如果你需要一個(gè) Wo...
    IT老馬閱讀 3,373評(píng)論 1 23
  • 為什么要使用Redux 我們知道React是一個(gè)簡(jiǎn)單的視圖層框架,React開發(fā)出的應(yīng)用是由許多組件構(gòu)建而成缎玫,如果...
    FTD止水閱讀 3,438評(píng)論 1 4
  • Redux Redux 是一個(gè)小型的獨(dú)立JS 庫(kù)兜畸,Redux 可以與任何 UI 框架集成,常與React 一起使用...
    QiShare閱讀 2,402評(píng)論 0 5
  • 完整代碼請(qǐng)看這里 上一篇文章主要介紹了 redux 文檔里所用到的基本優(yōu)化方案碘梢,但是很多都是手工實(shí)現(xiàn)的咬摇,不夠自動(dòng)化...
    寫代碼的海怪閱讀 2,149評(píng)論 0 2