<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Redux Toolkit 是個好東西

          共 6850字,需瀏覽 14分鐘

           ·

          2021-11-03 16:48

          前言

          hello 朋友們,我又來分享技術(shù)調(diào)研了,蕪湖~

          這次是 Readux Toolkit,它配合我上次調(diào)研的 proxy-memoize 一起來優(yōu)化一下我們項目現(xiàn)在的狀態(tài)管理。

          相信大部分小伙伴還是對 redux 更了解,那這個Readux Toolkit又是個啥東西的,能帶來啥,怎么用。那這篇文章可能能幫你解決這幾個疑問。當(dāng)然如果你想更詳細(xì)的了解的話肯定是要看官網(wǎng)的啦。

          那么話不多說,進入正題吧

          基于Redux優(yōu)化

          首先毫無疑問,Readux Toolkit是基于Redux的一系列優(yōu)化,那優(yōu)化了redux的什么呢,這里我就簡要的講一講redux可能存在的缺點(從一些角度說它的缺點也是了優(yōu)點,因場景而異啦):

          1. 我們很多狀態(tài)都要抽象到 store,一個變化就要對應(yīng)編寫 action,reducer
          2. 需要幾個軟件包來使Redux與React一起工作,例如redux-thunk、reselect
          3. Redux的一些理念導(dǎo)致我們需要寫很多樣板代碼
          4. 配置 Redux store太復(fù)雜

          當(dāng)然我們也不全是因為redux他的這些所謂的缺點,而非要卷來優(yōu)化哈,其實也是因為調(diào)研Readux Toolkit我才發(fā)現(xiàn)這redux的缺點,雖然是上級給的任務(wù),但是調(diào)研之后發(fā)現(xiàn)還是真香。

          需了解的知識

          首先當(dāng)然是要了解redux知識啦,有redux知識為了方便更迅速理解Readux Toolkit的實現(xiàn)或者他的妙用,還需要先了解他的核心依賴:

          • immer
          • redux
          • redux-thunk
          • reselect

          immer

          這幾個中我是不了解這個immer的,其他基本略知一二,那么就看看這個immer庫是個啥吧:

          這個庫,它允許我們把state的 不變的(immutable) 特性轉(zhuǎn)化為 可變的(mutable)

          具體上的實現(xiàn)它是利用了 proxy,當(dāng)我們對 state 進行修改,proxy對象會攔截,并且按順序替換上層對象,返回的新對象。看上去就好像自動幫你直接修改了state

          api

          首先看看整體的Api,然后再詳細(xì)說說可能會常用的:

          • configureStore (): 包裝 createStore 以提供簡化的配置選項和良好的默認(rèn)設(shè)置。它可以自動組合你的slice reducers,添加你提供的任何 Redux 中間件,默認(rèn)包括 Redux-thunk,并啟用 Redux DevTools 擴展。
          • createReducer () : 它允許您為 case reducer 函數(shù)提供一個動作類型查找表,而不是編寫 switch 語句。此外,它還自動使用 immer 庫,讓您使用普通的可變代碼編寫更簡單的不可變更新,比如 state.todos [3].complete = true。
          • createAction () : 為給定的動作類型字符串生成動作創(chuàng)建器函數(shù)。函數(shù)本身定義了 toString () ,因此可以使用它來代替類型常量。
          • createSlice () : 接受 reducer 函數(shù)的對象、片名和初始狀態(tài)值,并自動生成帶有相應(yīng)動作創(chuàng)建器和動作類型的 slice reducer。
          • createAsyncThunk: 接受一個操作類型字符串和一個返回promise函數(shù),并生成一個 thunk,該 thunk 根據(jù)該promise dispatches pending/fulfilled/rejected的action types
          • createEntityAdapter: 生成一組可重用的還原器和選擇器來管理存儲中的規(guī)范化數(shù)據(jù)
          • reselect庫中的 createSelector utility,為了方便使用而re-exported。

          configureStore

          step1configureStore,這個必不可少,用來創(chuàng)建一個空的Redux store,同時這里呢會自動配置 Redux DevTools 擴展,以便檢查存儲:

          import?{?configureStore?}?from?'@reduxjs/toolkit'
          export?const?store?=?configureStore({
          ????reducer:?{},
          })

          step2 是要< provider > 來使 redux 對 React 組件可用,將導(dǎo)出的store當(dāng)作prop傳遞給它,這一塊不必多說

          createSlice

          step3 這里會有點不一樣了,我們要通過 createSlice 創(chuàng)建一個Redux狀態(tài)切片(Redux State Slice),創(chuàng)建這個slice需要:

          1. 一個字符串名來標(biāo)識該片
          2. 一個初始狀態(tài)值
          3. 一個或多個 reducer 函數(shù)來定義如何更新該狀態(tài) 創(chuàng)建這個slice能干嘛?可以導(dǎo)出生成的 Redux 動作創(chuàng)建器和整個片的 reducer 函數(shù):
          import?{?createSlice?}?from?'@reduxjs/toolkit'

          const?initialState?=?{
          ??value:?0,
          }

          export?const?counterSlice?=?createSlice({
          ??name:?'counter',
          ??initialState,
          ??reducers:?{
          ????increment:?(state)?=>?{
          ??????/**?
          ???????* Redux Toolkit 允許我們在還原器中編寫“可變的(mutable)”邏輯。
          ???????*?它實際上并沒有改變狀態(tài),因為它使用?Immer?庫,
          ???????*?它將檢測對"draft?state"?的更改,并根據(jù)這些更改生成
          ???????*?一個全新的不可變狀態(tài)
          ???????*/

          ??????state.value?+=?1
          ????},
          ????decrement:?(state)?=>?{
          ??????state.value?-=?1
          ????},
          ????incrementByAmount:?(state,?action)?=>?{
          ??????state.value?+=?action.payload
          ????},
          ??},
          })

          //?為每個?reducer?函數(shù)生成動作創(chuàng)建器
          export?const?{?increment,?decrement,?incrementByAmount?}?=?counterSlice.actions

          export?default?counterSlice.reducer

          結(jié)合這個例子,可以清楚的看到這個createSlice接收的:一個字符串名來標(biāo)識該片也就是name,一個初始狀態(tài)值initialState,以及多個reducer行數(shù)。并且為每個 reducer 函數(shù)生成動作創(chuàng)建器。

          它有啥作用或者其他好處呢?可能一小部分人不看代碼,我把注釋給拿下來。

          我們知道 Redux 它是要求我們通過制作數(shù)據(jù)副本和更新副本來編寫所有狀態(tài)更新的。然而, createSlice 和 createReducer 在內(nèi)部使用 Immer 來允許我們編寫“可變的(mutable)”的更新邏輯,使其成為正確的不可變更的更新。

          Redux Toolkit 允許我們在還原器中編寫“mutable”邏輯。它實際上并沒有改變狀態(tài),因為它使用 Immer 庫,檢測對“draft state”的更改,并根據(jù)這些更改生成一個全新的不可變狀態(tài)

          step 4 ?我們需要從上面的創(chuàng)建的空的 store 導(dǎo)入 reducer 函數(shù)并將其添加到我們的存儲中,通過在 reducer 參數(shù)中定義一個字段,告訴 store 使用這個 slice reducer 函數(shù)來處理該狀態(tài)的所有更新。

          import?{?configureStore?}?from?'@reduxjs/toolkit'
          import?counterReducer?from?'../features/counter/counterSlice'

          export?default?configureStore({
          ??reducer:?{
          ????counter:?counterReducer,
          ??},
          })

          step 5 現(xiàn)在我們可以使用 React-Redux hook 讓 React 組件與 Redux 存儲交互。我們可以使用 useSelector 從存儲中讀取數(shù)據(jù),并使用 useDispatch 分派操作。

          理解的話我們看這個 counter 組件的例子:

          import?React?from?'react'
          import?{?useSelector,?useDispatch?}?from?'react-redux'
          import?{?decrement,?increment?}?from?'./counterSlice'

          export?function?Counter()?{
          ??const?count?=?useSelector((state)?=>?state.counter.value)
          ??const?dispatch?=?useDispatch()

          ??return?(
          ????<div>
          ??????<div>
          ????????<button?onClick={()?=>?dispatch(increment())}?>
          ??????????增加+
          ????????button>

          ????????<span>{count}span>
          ????????<button?onClick={()?=>?dispatch(decrement())}?>
          ??????????減少-
          ????????button>
          ??????div>
          ????div>
          ??)
          }

          當(dāng)點擊+、-按鈕時的動作,分析:

          • 相應(yīng)的 Redux action 將被派發(fā)(dispatched)到存儲區(qū)(store)
          • 這個 counter slice reducer將觀測actions并更新其狀態(tài)
          • < Counter > 組件將觀測到存儲(store)中新的狀態(tài)值,并使用新數(shù)據(jù)re-render自己

          例子

          這里也放一個簡單的例子,可以訪問codesandbox的可以戳這里,也可以去官網(wǎng)找這個例子。

          store.js 文件

          import?{?configureStore?}?from?'@reduxjs/toolkit';
          import?counterReducer?from?'../features/counter/counterSlice';

          export?default?configureStore({
          ????reducer:?{
          ????????counter:?counterReducer,
          ????},
          });

          counterSlice.js 文件

          import?{?createSlice?}?from?'@reduxjs/toolkit';

          export?const?slice?=?createSlice({
          ????name:?'counter',
          ????initialState:?{
          ????????value:?0,
          ????},
          ????reducers:?{
          ????????increment:?state?=>?{
          ????????????state.value?+=?1;
          ????????},
          ????????decrement:?state?=>?{
          ????????????state.value?-=?1;
          ????????},
          ????????incrementByAmount:?(state,?action)?=>?{
          ????????????state.value?+=?action.payload;
          ????????},
          ????},
          });

          export?const?{?increment,?decrement,?incrementByAmount?}?=?slice.actions;

          export?const?incrementAsync?=?amount?=>?dispatch?=>?{
          ????setTimeout(()?=>?{
          ????????dispatch(incrementByAmount(amount));
          ????},?1000);
          };

          export?const?selectCount?=?state?=>?state.counter.value;
          export?default?slice.reducer;

          Counter.js 文件

          import?React,?{?useState?}?from?'react';
          import?{?useSelector,?useDispatch?}?from?'react-redux';
          import?{
          ????decrement,
          ????increment,
          ????incrementByAmount,
          ????incrementAsync,
          ????selectCount,
          }?from?'./counterSlice';
          import?styles?from?'./Counter.module.css';

          export?function?Counter()?{
          const?count?=?useSelector(selectCount);
          const?dispatch?=?useDispatch();
          const?[incrementAmount,?setIncrementAmount]?=?useState('2');

          return?(
          <div>
          ????<div>
          ????????<button?onClick={()?=>?dispatch(increment())}?>
          ????????+
          ????????button>

          ????????<span>{count}span>
          ????????<button?onClick={()?=>?dispatch(decrement())}?>
          ????????-
          ????????button>
          ????div>

          ????<div>
          ????????<input
          ????????value={incrementAmount}
          ????????onChange={e?=>
          ?setIncrementAmount(e.target.value)}
          ????????/>

          ????????<button
          ????????onClick={()?=>

          ????????dispatch(incrementByAmount(Number(incrementAmount)?||?0))
          ????????}
          ????????>
          ????????Add?Amount
          ????????button>

          ????????<button?onClick={()?=>?dispatch(incrementAsync(Number(incrementAmount)?||?0))}?>
          ????????Add?Async
          ????????button>
          ????div>
          div>
          );
          }

          index.js 文件

          import?React?from?'react';
          import?ReactDOM?from?'react-dom';
          import?{?Provider?}?from?'react-redux';
          import?'./index.css';
          import?App?from?'./App';
          import?store?from?'./app/store';

          ReactDOM.render(
          ????<Provider?store={store}>
          ????????<App?/>
          ????Provider>
          ,
          ????document.getElementById('root')
          );

          總結(jié)

          這里簡要的講一下這個簡單例子的整體的步驟:

          1. 使用 configureStore 創(chuàng)建 Redux 存儲
          • configureStore 接受作為命名參數(shù)的 reducer 函數(shù)
          • configureStore 自動設(shè)置好了默認(rèn)設(shè)置
          向 React 應(yīng)用程序組件提供 Redux 存儲
          • 在 組件外包裹 React-Redux < Provider > 組件
          • < Provider store = { store } >
          使用 createSlice 創(chuàng)建一個 Redux“ slice”reducer
          • 使用字符串名稱、初始 state 和 reducer 函數(shù)調(diào)用 createSlice
          • Reducer 函數(shù)可能使用 Immer“變異(mutate)”狀態(tài)
          • 導(dǎo)出生成的slice reducer 和 action creators
          在 React 組件中使用 redux useSelector/useDispatch 掛鉤
          • 使用 useSelector 鉤子從 store 中讀取數(shù)據(jù)
          • 使用 useDispatch 鉤子獲取 dispatch 函數(shù),并根據(jù)需要進行 dispatch actions 操作

          OK,大概就總結(jié)道這里了,你會發(fā)現(xiàn)還有一些主要的api沒有講到,比如很重要的createReducer 和 createAction這些還沒講,但是這個小應(yīng)用也能實現(xiàn)了(這個例子的場景限制發(fā)揮了呀)。

          那其實你知道這些基本就能使用了,還有就是這篇也沒講到 use Redux Toolkit and React-Redux with TypeScript,下篇我們詳細(xì)講一下搭配 TypeScript 如何使用以及他的好處吧。

          ??????????

          非常感謝你看到這,如果覺得不錯的話點個贊 ? 吧

          今天也是在努力變強不變禿的 HearLing 呀 ??

          ??????????


          瀏覽 128
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青免费在线观看高清无码视频 | 日韩无修正| 我想天天肏你 | 亚洲一区高清无码 | 看A片视频 |