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

React?TypeScript?應(yīng)用中便捷使用Redux?Toolkit方法詳解

 更新時(shí)間:2022年11月22日 10:44:59   作者:BokFang  
這篇文章主要為大家介紹了React?TypeScript?應(yīng)用中便捷使用Redux?Toolkit方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

本文介紹的主要內(nèi)容是 Redux-Toolkit 在 React + TypeScript 大型應(yīng)用中的實(shí)踐,主要解決的問題是使用 createSlice 的前提下消費(fèi) redux 狀態(tài)仍舊有點(diǎn)繁瑣的問題。

閱讀本文需要的前置知識(shí):了解 React 、Redux-Toolkit 、TypeScript 的使用。

關(guān)于 Redux-Toolkit 提供的各種函數(shù)的使用,大家可以去官網(wǎng) redux-toolkit.js.org/ 學(xué)習(xí)。

背景

前陣子接到一個(gè)任務(wù):在使用 redux 作為狀態(tài)管理工具的前提下,優(yōu)化一下消費(fèi) redux 的步驟,并制定一套使用規(guī)范,讓大家在開發(fā)這個(gè)項(xiàng)目消費(fèi) redux 狀態(tài)時(shí)能按照規(guī)范來。

說到簡化消費(fèi) redux 步驟,我第一時(shí)間想到的就是 redux 官方推薦的 Redux-Toolkit,于是我就去學(xué)習(xí)了一下 Redux-Toolkit。

了解完官網(wǎng)和網(wǎng)上各種文章后,我知道了 Redux-Toolkit 在項(xiàng)目中的使用,但是仍然有一個(gè)疑問:使用了 createSlice 后,仍然需要在項(xiàng)目的組件中使用 useDispatch 來更新狀態(tài),還是有點(diǎn)麻煩。對(duì)于組件使用者來說,有沒有更方便的方式消費(fèi) redux 狀態(tài)?

在網(wǎng)上逛來逛去,沒找到有人發(fā)相關(guān)的文章,所以我準(zhǔn)備自己動(dòng)手試試看。

Redux-Toolkit 常規(guī)使用

我們先來看看目前使用 Redux-Toolkit 消費(fèi) redux 狀態(tài)的方式。舉個(gè)例子,假設(shè)我們現(xiàn)在的業(yè)務(wù)和蛋糕有關(guān),有兩個(gè)狀態(tài)存在 redux,分別是 nameOfCake 和 numOfCakes,我們使用 createSlice 來創(chuàng)建 reducer 和 actions:

// 文件位置: app/src/store/reducers/cake.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
type InitialState = {
  numOfCakes: number;
  nameOfCake: string;
};
const initialState: InitialState = {
  numOfCakes: 20,
  nameOfCake: 'great cake',
};
const cakeSlice = createSlice({
  name: 'cake',
  initialState,
  reducers: {
    updateCakeNum: (state, action: PayloadAction<number>) => {
      state.numOfCakes = action.payload;
    },
    updateCakeName: (state, action: PayloadAction<string>) => {
      state.nameOfCake = action.payload;
    },
  },
});
export default cakeSlice.reducer;
export const { updateCakeNum, updateCakeName } = cakeSlice.actions;

接著我們?cè)诮M件中消費(fèi):

// 文件位置: app/src/pages/Cake/components/CakeView/index.tsx
import { RootState } from '@/src/store';
import { useSelector, useDispatch } from 'react-redux';
import {
  useRecordReduxFunction,
  updateCakeNum,
  updateCakeName,
} from '@/src/store/reducers/cake';
export const CakeView = () => {
  const numOfCakes = useSelector((state: RootState) => state.cake.numOfCakes);
  const nameOfCake = useSelector((state: RootState) => state.cake.nameOfCake);
  const dispatch = useDispatch();
  const updateNum = () => {
    dispatch(updateCakeNum(100));
  };
  const updateName = () => {
    dispatch(updateCakeName('best cake'));
  };
  return (
    <div>
      <h3>Number of cakes - {numOfCakes}</h3>
      <h3>Name of cakes - {nameOfCake}</h3>
      <button onClick={updateName}>change cake's name</button>
      <button onClick={updateNum}>change cake's number</button>
    </div>
  );
};

現(xiàn)狀的繁瑣點(diǎn):

  • 每次使用 useSelector 來獲取 redux 中狀態(tài)的時(shí)候,都需要給 state 加一個(gè) ts 類型 RootState
  • 每次修改 redux 狀態(tài)時(shí),都需要引入 useDispatch 和一個(gè) updateData,再將調(diào)用 updateData 返回的action 給 dispatch

我們的目標(biāo)就是優(yōu)化現(xiàn)狀的這兩個(gè)繁瑣點(diǎn)。

優(yōu)化方案

優(yōu)化 useDispatch 和 useSelector

對(duì)于繁瑣點(diǎn)1,我們可以對(duì) useDispatch 和 useSelector 進(jìn)行簡單的封裝,增加 ts 類型校驗(yàn)。代碼如下:

// 文件位置: app/src/hooks/useReduxHook.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from '../store';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

其中 RootState 和 AppDispatch 在 store 中導(dǎo)出:

import { configureStore } from '@reduxjs/toolkit';
import cakeReducer from './reducers/cake';
const store = configureStore({
  reducer: {
    cake: cakeReducer,
  }
})
export default store;
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

通過簡單的封裝,我們?cè)跇I(yè)務(wù)層就用 useAppSelector 和 useAppDispatch 代替 useSelector 和 useDispatch:

import { useAppSelector, useAppDispatch } from '@src/hooks/useReduxHook';
// ...
export const CakeView = () => {
  const numOfCakes = useAppSelector((state) => state.cake.numOfCakes);
  const nameOfCake = useAppSelector((state) => state.cake.nameOfCake);
  const dispatch = useAppDispatch();
	// ...
  return (
	// ...
  );
};

可以看到這樣就有 ts 類型提示或者校驗(yàn)了:

優(yōu)化修改 redux 狀態(tài)的步驟

我們現(xiàn)在想要在業(yè)務(wù)組件中修改 redux 狀態(tài),我們就需要引入 useDispatch 和通過 createSlice 生成的 updateData 函數(shù),再調(diào)用 dispatch(updateData(data)) 來更新狀態(tài)。

能不能優(yōu)化成,業(yè)務(wù)組件只需要調(diào)用一個(gè) updateData 函數(shù),就可以更新 redux 狀態(tài)呢?

最簡單的方式就是將 dispatch(updateData(data)) 給抽出去:

const useUpdateCakeName = () => {
  const dispatch = useAppDispatch();
  return (payload: InitialState['nameOfCake']) => {
    dispatch(updateCakeName(payload));
  };
};

但是這對(duì)于開發(fā)者來講,換湯不換藥,還是需要寫一個(gè) hook 來 dispatch action。

那我們就來寫一個(gè)能自動(dòng)生成 「用于dispatch action 的 updateData 函數(shù)」的 hook 吧。先來個(gè) js 版:

const useCakeReduxFunction = (action) => {
  const dispatch = useAppDispatch();
  return (payload) => {
    dispatch(cakeSlice.actions[action](payload));
  };
};

這個(gè)倒是好用了一些,業(yè)務(wù)組件使用起來是這樣的:

import { useCakeReduxFunction } from '@/src/store/reducers/cake';
// ...
export const CakeView = () => {
  const updateNum = useCakeReduxFunction('updateCakeNum');
  const updateName = useCakeReduxFunction('updateCakeName');
	// ...
  return (
	// ...
  );
};

但是還有個(gè)問題,這樣的話每個(gè) reducer 里都要寫一個(gè) useDataReduxFunction,還是不夠便捷。我們就自然而然的想到寫一個(gè) useCreateReduxFunction 來簡化開發(fā)流程。useCreateReduxFunction 的代碼如下;

type GetArrFirst<T> = T extends [infer Res, ...infer P] ? Res : unknown;
export const useCreateReduxFunction = <S extends Slice>(slice: S) => {
  return <T extends keyof S['actions']>(name: T) => {
    const dispatch = useAppDispatch();
    const actionCreator = (slice.actions as S['actions'])[name];
    return (payload: GetArrFirst<Parameters<typeof actionCreator>>) => {
      dispatch(actionCreator(payload));
    };
  };
};

這樣就好辦了,我們?cè)?reducer 中這樣使用:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { useCreateReduxFunction } from '../../app/hooks';
type InitialState = {
  numOfCakes: number;
  cakeName: string;
};
const initialState: InitialState = {
  numOfCakes: 20,
  cakeName: 'great cake',
};
const cakeSlice = createSlice({
  name: 'cake',
  initialState,
  reducers: {
    updateCakeNum: (state, action: PayloadAction<number>) => {
      state.numOfCakes = action.payload;
    },
    updateCakeName: (state, action: PayloadAction<string>) => {
      state.cakeName = action.payload;
    },
  },
});
export const useCakeReduxFunction = useCreateReduxFunction(cakeSlice);
export default cakeSlice.reducer;
export const { updateCakeNum, updateCakeName } = cakeSlice.actions;

在業(yè)務(wù)方這么使用:

import { useAppSelector } from '@src/hooks/useReduxHook';
import { useCakeReduxFunction } from '@src/store/reducers/cake';
export const CakeView = () => {
  const numOfCakes = useAppSelector((state) => state.cake.numOfCakes);
  const nameOfCake = useAppSelector((state) => state.cake.cakeName);
  const updateNum = useCakeReduxFunction('updateCakeNum');
  const updateName = useCakeReduxFunction('updateCakeName');
  return (
    <div>
      <h3>Number of cakes - {numOfCakes}</h3>
      <h3>Name of cakes - {nameOfCake}</h3>
      <button onClick={() => {updateName('best cake')}}>change cake's name</button>
      <button onClick={() => {updateNum(100)}}>change cake's number</button>
    </div>
  );
};

這樣就達(dá)成我們的目標(biāo)了。

總結(jié)

核心代碼如下:

type GetArrFirst<T> = T extends [infer Res, ...infer P] ? Res : unknown;
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useCreateReduxFunction = <S extends Slice>(slice: S) => {
  return <T extends keyof S['actions']>(name: T) => {
    const dispatch = useAppDispatch();
    const actionCreator = (slice.actions as S['actions'])[name];
    return (payload: GetArrFirst<Parameters<typeof actionCreator>>) => {
      dispatch(actionCreator(payload));
    };
  };
};

經(jīng)過上面的優(yōu)化方案,我們封裝了 useAppSelector 、 useAppDispatch 和 useCreateReduxFunction三個(gè) hook,解決了目前使用 Redux-Toolkit 還會(huì)存在的一些繁瑣點(diǎn)。

以上就是React TypeScript 應(yīng)用中便捷使用Redux Toolkit方法詳解的詳細(xì)內(nèi)容,更多關(guān)于React TypeScript使用Redux Toolkit的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談從React渲染流程分析Diff算法

    淺談從React渲染流程分析Diff算法

    這篇文章主要介紹了淺談從React渲染流程分析Diff算法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • React?Hooks--useEffect代替常用生命周期函數(shù)方式

    React?Hooks--useEffect代替常用生命周期函數(shù)方式

    這篇文章主要介紹了React?Hooks--useEffect代替常用生命周期函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 基于React實(shí)現(xiàn)搜索GitHub用戶功能

    基于React實(shí)現(xiàn)搜索GitHub用戶功能

    在本篇博客中,我們將介紹如何在 React 應(yīng)用中搜索 GitHub 用戶并顯示他們的信息,文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • Remix如何支持原生?CSS方法詳解

    Remix如何支持原生?CSS方法詳解

    這篇文章主要為大家介紹了Remix如何支持原生CSS的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • react執(zhí)行【npx create-react-app my-app】出現(xiàn)常見錯(cuò)誤的解決辦法

    react執(zhí)行【npx create-react-app my-app】出現(xiàn)常見錯(cuò)誤的解決辦法

    文章主要介紹了在使用npx創(chuàng)建React應(yīng)用時(shí)可能遇到的幾種常見錯(cuò)誤及其解決方法,包括缺少依賴、網(wǎng)絡(luò)問題和npx解析錯(cuò)誤等,并提供了相應(yīng)的解決措施,此外,還提到了使用騰訊云云產(chǎn)品來支持React應(yīng)用開發(fā)
    2024-11-11
  • react-native-fs實(shí)現(xiàn)文件下載、文本存儲(chǔ)的示例代碼

    react-native-fs實(shí)現(xiàn)文件下載、文本存儲(chǔ)的示例代碼

    本篇文章主要介紹了react-native-fs實(shí)現(xiàn)文件下載、文本存儲(chǔ)的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解下
    2017-09-09
  • React.cloneElement的使用詳解

    React.cloneElement的使用詳解

    這篇文章主要介紹了React.cloneElement的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下
    2021-04-04
  • React自定義實(shí)現(xiàn)useWatch的方式和特點(diǎn)

    React自定義實(shí)現(xiàn)useWatch的方式和特點(diǎn)

    這篇文章主要介紹了React自定義實(shí)現(xiàn)useWatch的方式和特點(diǎn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-05-05
  • 如何應(yīng)用?SOLID?原則在?React?中整理代碼之開閉原則

    如何應(yīng)用?SOLID?原則在?React?中整理代碼之開閉原則

    React?不是面向?qū)ο?,但這些原則背后的主要思想可能是有幫助的,在本文中,我將嘗試演示如何應(yīng)用這些原則來編寫更好的代碼,對(duì)React?SOLID原則開閉原則相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-07-07
  • React使用高德地圖的實(shí)現(xiàn)示例(react-amap)

    React使用高德地圖的實(shí)現(xiàn)示例(react-amap)

    這篇文章主要介紹了React使用高德地圖的實(shí)現(xiàn)示例(react-amap),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評(píng)論

尚志市| 远安县| 马关县| 大同市| 内黄县| 理塘县| 石阡县| 耒阳市| 连州市| 项城市| 南岸区| 绍兴市| 霸州市| 民勤县| 珠海市| 西城区| 马尔康县| 湟中县| 扶沟县| 衡南县| 抚宁县| 蕉岭县| 封开县| 竹山县| 荣成市| 碌曲县| 德昌县| 子长县| 兰西县| 灵璧县| 迭部县| 广丰县| 洛宁县| 铜山县| 句容市| 松江区| 绥中县| 镇赉县| 沧州市| 前郭尔| 彩票|