国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(二) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級項(xiàng)目(十七)

這篇具有很好參考價(jià)值的文章主要介紹了【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(二) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級項(xiàng)目(十七)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


學(xué)習(xí)內(nèi)容來源:React + React Hook + TS 最佳實(shí)踐-慕課網(wǎng)


相對原教程,我在學(xué)習(xí)開始時(shí)(2023.03)采用的是當(dāng)前最新版本:

項(xiàng) 版本
react & react-dom ^18.2.0
react-router & react-router-dom ^6.11.2
antd ^4.24.8
@commitlint/cli & @commitlint/config-conventional ^17.4.4
eslint-config-prettier ^8.6.0
husky ^8.0.3
lint-staged ^13.1.2
prettier 2.8.4
json-server 0.17.2
craco-less ^2.0.0
@craco/craco ^7.1.0
qs ^6.11.0
dayjs ^1.11.7
react-helmet ^6.1.0
@types/react-helmet ^6.1.6
react-query ^6.1.0
@welldone-software/why-did-you-render ^7.0.1
@emotion/react & @emotion/styled ^11.10.6

具體配置、操作和內(nèi)容會(huì)有差異,“坑”也會(huì)有所不同。。。


一、項(xiàng)目起航:項(xiàng)目初始化與配置

  • 一、項(xiàng)目起航:項(xiàng)目初始化與配置

二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表

  • 二、React 與 Hook 應(yīng)用:實(shí)現(xiàn)項(xiàng)目列表

三、TS 應(yīng)用:JS神助攻 - 強(qiáng)類型

  • 三、 TS 應(yīng)用:JS神助攻 - 強(qiáng)類型

四、JWT、用戶認(rèn)證與異步請求

  • 四、 JWT、用戶認(rèn)證與異步請求(上)

  • 四、 JWT、用戶認(rèn)證與異步請求(下)

五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式

  • 五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式(上)

  • 五、CSS 其實(shí)很簡單 - 用 CSS-in-JS 添加樣式(下)

六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(上)

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(中)

  • 六、用戶體驗(yàn)優(yōu)化 - 加載中和錯(cuò)誤狀態(tài)處理(下)

七、Hook,路由,與 URL 狀態(tài)管理

  • 七、Hook,路由,與 URL 狀態(tài)管理(上)

  • 七、Hook,路由,與 URL 狀態(tài)管理(中)

  • 七、Hook,路由,與 URL 狀態(tài)管理(下)

八、用戶選擇器與項(xiàng)目編輯功能

  • 八、用戶選擇器與項(xiàng)目編輯功能(上)

  • 八、用戶選擇器與項(xiàng)目編輯功能(下)

九、深入React 狀態(tài)管理與Redux機(jī)制

1&2

  • 九、深入React 狀態(tài)管理與Redux機(jī)制(一)

3.合并組件狀態(tài),實(shí)現(xiàn)useUndo

功能描述:

可以對一個(gè)數(shù)字進(jìn)行不斷地賦值,同時(shí)記錄下歷史值;可以通過undo對當(dāng)前值進(jìn)行撤銷操作,一步步地回到最初值。在進(jìn)行撤銷操作的同時(shí),記錄下undo掉的值;通過redo可以回到undo之前的值,不斷地redo最終可以回到執(zhí)行所有撤銷操作之前的值。

代碼實(shí)現(xiàn)

使用useState實(shí)現(xiàn)該hook,由于多個(gè)state值之前相互引用。因此useCallback的依賴項(xiàng)中會(huì)填入多個(gè)state作為依賴項(xiàng),但是在useCallback的回調(diào)函數(shù)中,在調(diào)用時(shí)會(huì)更新state值導(dǎo)致頁面重新渲染,useCallback的回調(diào)函數(shù)也被重新定義了。

接下來模仿實(shí)現(xiàn) use-undo

  • use-undo-demo - CodeSandbox
  • use-undo - npm

新建 src\utils\use-undo.ts

import { useState } from "react";

export const useUndo = <T>(initialPresent: T) => {
  // 記錄歷史操作的合集
  const [past, setPast] = useState<T[]>([])
  const [present, setPresent] = useState(initialPresent)
  // 記錄未來操作的合集
  const [future, setFuture] = useState<T[]>([])

  const canUndo = past.length !== 0
  const canRedo = future.length !== 0

  const undo = () => {
    if (!canUndo) return

    const previous = past[past.length - 1]
    const newPast = past.slice(0, past.length - 1)

    setPast(newPast)
    setPresent(previous)
    setFuture([present, ...future])
  }

  const redo = () => {
    if (!canRedo) return

    const next = future[0]
    const newFuture = future.slice(1)

    setFuture(newFuture)
    setPresent(next)
    setPast([...past, present])
  }

  const set = (newPresent: T) => {
    if (newPresent === present) {
      return
    }
    setPast([...past, present])
    setPresent(newPresent)
    setFuture([])
  }

  const reset = (newPresent: T) => {
    setPast([])
    setPresent(newPresent)
    setFuture([])
  }

  return [
    {past, present, future},
    {redo, undo, set, reset, canRedo, canUndo}
  ] as const
}

現(xiàn)需要對代碼做以下優(yōu)化:

  • 使用 useCallback 避免 造成之前的那種 依賴不等導(dǎo)致的循環(huán)渲染
  • 將用到的 變量合并聲明 后續(xù)也同步改動(dòng)
  • SetXXX 使用函數(shù)形式 直接使用歷史狀態(tài) 避免外界狀態(tài)的使用,減少依賴
import { useCallback, useState } from "react";

export const useUndo = <T>(initialPresent: T) => {
  // 合并聲明
  const [state, setState] = useState<{
    past: T[],
    present: T,
    future: T[]
  }>({
    past: [],
    present: initialPresent,
    future: []
  })
  
  // 另一種寫法
  // const [state, setState] = useState({
  //   past: [] as T[],
  //   present: initialPresent as T,
  //   future: [] as T[]
  // })

  const canUndo = state.past.length !== 0
  const canRedo = state.future.length !== 0

  const undo = useCallback(() => {
    setState(currentState => {
      const { past, present, future } = currentState
      if (past.length === 0) return currentState
   
      const previous = past[past.length - 1]
      const newPast = past.slice(0, past.length - 1)
   
      return {
        past: newPast,
        present: previous,
        future: [present, ...future]
      }
    })
  }, [])
  

  const redo = useCallback(() => {
    setState(currentState => {
      const { past, present, future } = currentState
      if (future.length === 0) return currentState
  
      const next = future[0]
      const newFuture = future.slice(1)

      return {
        past: [...past, present],
        present: next,
        future: newFuture
      }
    })
  }, [])

  const set = useCallback((newPresent: T) => {
    setState(currentState => {
      const { past, present } = currentState
      if (newPresent === present) {
        return currentState
      }
      return {
        past: [...past, present],
        present: newPresent,
        future: []
      }
    })
  }, [])

  const reset = useCallback((newPresent: T) => {
    setState({
      past: [],
      present: newPresent,
      future: []
    })
  }, [])

  return [
    state,
    {redo, undo, set, reset, canRedo, canUndo}
  ] as const
}

4.用useReducer進(jìn)行狀態(tài)管理

替代方案:

useReducer作為useState 的替代方案。它接收一個(gè)形如 (state, action) => newState的 reducer,并返回當(dāng)前的 state 以及與其配套的 dispatch 方法。

相比較于useState,useReducer 具有如下優(yōu)點(diǎn):

  • state中的狀態(tài)值之間相互關(guān)聯(lián);
  • 下一個(gè) state的更新依賴于之前的 state
  • useReducer | Hook API 索引 – React

下面使用 useReducer 再對 use-undo 進(jìn)行改寫

編輯 src\utils\use-undo.ts

import { useCallback, useReducer, useState } from "react";

const UNDO = 'UNDO'
const REDO = 'REDO'
const SET = 'SET'
const RESET = 'RESET'

type State<T> = {
  past: T[];
  present: T;
  future: T[];
}

type Action<T> = { newPresent?: T, type: typeof UNDO | typeof REDO | typeof SET | typeof RESET }

const undoReducer = <T>(state: State<T>, action: Action<T>) => {
  const { past, present, future } = state
  const { newPresent, type } = action

  switch(type) {
    case UNDO: {
      if (past.length === 0) return state;

      const previous = past[past.length - 1];
      const newPast = past.slice(0, past.length - 1);

      return {
        past: newPast,
        present: previous,
        future: [present, ...future],
      };
    }
    case REDO: {
      if (future.length === 0) return state;

      const next = future[0];
      const newFuture = future.slice(1);

      return {
        past: [...past, present],
        present: next,
        future: newFuture,
      };
    }
    case SET: {
      if (newPresent === present) {
        return state;
      }
      return {
        past: [...past, present],
        present: newPresent,
        future: [],
      };
    }
    case RESET: {
      return {
        past: [],
        present: newPresent,
        future: [],
      }
    }
    default: 
      return state
  }
}

export const useUndo = <T>(initialPresent: T) => {
  const [state, dispatch] = useReducer(undoReducer, {
    past: [],
    present: initialPresent,
    future: [],
  } as State<T>)

  const canUndo = state.past.length !== 0;
  const canRedo = state.future.length !== 0;

  const undo = useCallback(() => dispatch({ type: UNDO }), []);

  const redo = useCallback(() => dispatch({ type: REDO }), []);

  const set = useCallback((newPresent: T) => dispatch({newPresent, type: SET}), []);

  const reset = useCallback((newPresent: T) => dispatch({newPresent, type: RESET}), []);

  return [state, { redo, undo, set, reset, canRedo, canUndo }] as const;
};

統(tǒng)一狀態(tài)管理后 雖然代碼量多了,但是經(jīng)過多重封裝,層次更加清晰

可以發(fā)現(xiàn) useReducer 相對 useState 適合定義多個(gè)相互影響的狀態(tài)量

鑒于 useReducer 針對復(fù)雜的state關(guān)系和更新的前后依賴的優(yōu)勢,因此 useAsync 非常適合使用 useReducer 來重構(gòu)

接下來使用 useReducer 改造一下 與 use-undo 結(jié)構(gòu)類似的 use-async(src\utils\use-async.ts):

...
const useSafeDispatch = <T>(dispatch: (...args: T[]) => void) => {
  const mountedRef = useMountedRef()
  return useCallback((...args: T[]) => (mountedRef.current ? dispatch(...args) : void 0), [dispatch, mountedRef])
}

export const useAsync = <D>(...) => {
  const config = { ...defaultConfig, ...initialConfig };
  const [state, dispatch] = useReducer((state: State<D>, action: Partial<State<D>>) => ({...state, ...action}), {
    ...defaultInitialState,
    ...initialState,
  });
  const safeDispatch = useSafeDispatch(dispatch);
  const [rerun, setRerun] = useState(() => () => {});

  const setData = useCallback(
    (data: D) =>
      safeDispatch(...),
    [safeDispatch]
  );

  const setError = useCallback(
    (error: Error) =>
      safeDispatch(...),
    [safeDispatch]
  );

  // run 來觸發(fā)異步請求
  const run = useCallback(
    (...) => {
      ...
      safeDispatch({ stat: "loading" });
      return promise
        .then((data) => {
          setData(data);
          return data;
        })
        .catch(...);
    },
    [config.throwOnError, safeDispatch, setData, setError]
  );
  ...
};

部分引用筆記還在草稿階段,敬請期待。。。文章來源地址http://www.zghlxwxcb.cn/news/detail-622223.html

到了這里,關(guān)于【實(shí)戰(zhàn)】 九、深入React 狀態(tài)管理與Redux機(jī)制(二) —— React17+React Hook+TS4 最佳實(shí)踐,仿 Jira 企業(yè)級項(xiàng)目(十七)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包