欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React?Hooks useReducer?逃避deps組件渲染次數增加陷阱

 更新時間:2022年09月06日 16:45:22   作者:qwer  
這篇文章主要介紹了React?Hooks?之?useReducer?逃避deps后增加組件渲染次數的陷阱詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

在快樂使用 React Hooks 開發(fā)自定義 Hooks 過程中,使用了 useEffect,useReducer,useRef,useCallback 等官方提供的 Hooks,將一些通用邏輯抽離出來,提高代碼復用性。

但在組合使用 useEffect,useReducerReact.memo 時,發(fā)生了組件在狀態(tài)未發(fā)生變化時觸發(fā)渲染,因為此動作發(fā)生在 mousemove 鼠標移動時,所以組件不必要渲染次數非常多。

自定義 Hooks 簡單實現

import { useReducer } from "react";
const reducer = (state, action) => {
  const { sliding, lastPos, ratio } = state;
  switch (action.type) {
    case "start":
      return {
        ...state,
        slideRange: action.slideRange,
        lastPos: action.x,
        sliding: true,
      };
    case "move":
      if (!sliding) {
        return state;
      }
      const offsetX = action.x - lastPos;
      const newRatio = ratio + offsetX / state.slideRange;
      if (newRatio > 1 || newRatio < 0) {
        return state;
      }
      return {
        ...state,
        lastPos: action.x,
        ratio: newRatio,
      };
    case "end":
      if (!sliding) {
        return state;
      }
      return {
        ...state,
        sliding: false,
      };
    case "updateRatio":
      return {
        ...state,
        ratio: action.ratio,
      };
    default:
      return state;
  }
};
export function useSlider(initialState) {
    const [state, dispatch] = useReducer(reducer, initialState);
    return [state, dispatch];
}

在組件中使用自定義 Hooks

const [state, dispatch] = useSlider(initialState);
  const { ratio, sliding, lastPos, slideRange } = state;
  useEffect(() => {
    const onSliding = (e) => {
      dispatch({ type: "move", x: e.pageX });
    };
    const onSlideEnd = () => {
      dispatch({ type: "end" });
    };
    document.addEventListener("mousemove", onSliding);
    document.addEventListener("mouseup", onSlideEnd);
    return () => {
      document.removeEventListener("mousemove", onSliding);
      document.removeEventListener("mouseup", onSlideEnd);
    };
  }, [dispatch]);
  const handleThumbMouseDown = useCallback(
    (event) => {
      const hotArea = hotAreaRef.current;
      dispatch({
        type: "start",
        x: event.pageX,
        slideRange: hotArea.clientWidth,
      });
      if (event.target.className !== "point") {
        dispatch({
          type: "updateRatio",
          ratio: (event.pageX - 30) / hotArea.clientWidth,
        });
      }
    },
    [dispatch]
  );

鼠標每次移動,都會觸發(fā) dispatch({ type: "move", x: e.pageX }),在 reducer 函數中,當 !sliding 時,不修改 state 數據原樣返回,但是組件仍然進行了渲染。

提前阻止 dispatch 觸發(fā)

sliding 判斷移動到 useEffect 中,提前阻止 dispatch 觸發(fā),并將 sliding 設置到 useEffect(fn, deps) deps 中,保證監(jiān)聽函數中能取到 sliding 最新值。

useEffect(() => {
    const onSliding = (e) => {
      if(!sliding) {
        return;
      }
      dispatch({ type: "move", x: e.pageX });
    };
    const onSlideEnd = () => {
      if (!sliding) {
        return;
      }
      dispatch({ type: "end" });
    };
    document.addEventListener("mousemove", onSliding);
    document.addEventListener("mouseup", onSlideEnd);
    return () => {
      document.removeEventListener("mousemove", onSliding);
      document.removeEventListener("mouseup", onSlideEnd);
    };
  }, [sliding]);

優(yōu)化后再測試

鼠標僅移動時,slidingfalse,直接 return,不會觸發(fā) dispatch 動作。

好處

避免了組件在 state 未修改時不必要渲染。

壞處

部分處理邏輯被移動到使用自定義 hooks 的組件中,sliding 數據改變時,add EventListener函數會重新注冊。

結論

不能為了不在 useEffect(fn, deps) 設置 deps,使用 useReducer,并把所有數據變更都放在 reducer 中。 本篇文章通過把不修改 reducer state 的動作提前阻止,避免使用此自定義 hooks 的組件發(fā)生不必要渲染,提高代碼復用性的同時也兼顧了組件性能。

題外

  • React.memoprops 進行淺比較,一種組件性能優(yōu)化方式
  • useCallback(fn, deps) 緩存函數
  • useMemo(() => fn, deps) 緩存昂貴變量
  • useState(initialState)惰性初始state,initialState` 只會在組件初始渲染中起作用,后續(xù)渲染時會被

參考文獻

React 官方文檔

以上就是React Hooks 之 useReducer 逃避deps后增加組件渲染次數的陷阱的詳細內容,更多關于React Hooks useReducer組件渲染的資料請關注腳本之家其它相關文章!

相關文章

  • react router 4.0以上的路由應用詳解

    react router 4.0以上的路由應用詳解

    本篇文章主要介紹了react router 4.0以上的路由應用詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • react如何修改循環(huán)數組對象的數據

    react如何修改循環(huán)數組對象的數據

    這篇文章主要介紹了react如何修改循環(huán)數組對象的數據問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • create-react-app中添加less支持的實現

    create-react-app中添加less支持的實現

    這篇文章主要介紹了react.js create-react-app中添加less支持的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • React實現復雜搜索表單的展開收起功能

    React實現復雜搜索表單的展開收起功能

    本節(jié)對于需要展開收起效果的查詢表單進行概述,主要涉及前端樣式知識。對React實現復雜搜索表單的展開-收起功能感興趣的朋友一起看看吧
    2021-09-09
  • 使用?React?Hooks?重構類組件的示例詳解

    使用?React?Hooks?重構類組件的示例詳解

    這篇文章主要介紹了如何使用?React?Hooks?重構類組件,本文就來通過一些常見示例看看如何使用 React Hooks 來重構類組件,需要的朋友可以參考下
    2022-07-07
  • React 子組件向父組件傳值的方法

    React 子組件向父組件傳值的方法

    本篇文章主要介紹了React 子組件向父組件傳值的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • TypeScript在React項目中的使用實踐總結

    TypeScript在React項目中的使用實踐總結

    這篇文章主要介紹了TypeScript在React項目中的使用總結,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • D3.js(v3)+react 實現帶坐標與比例尺的柱形圖 (V3版本)

    D3.js(v3)+react 實現帶坐標與比例尺的柱形圖 (V3版本)

    這篇文章主要介紹了D3.js(v3)+react 制作 一個帶坐標與比例尺的柱形圖 (V3版本) ,本文通過實例代碼文字相結合的形式給大家介紹的非常詳細,需要的朋友可以參考下
    2019-05-05
  • React模仿網易云音樂實現一個音樂項目詳解流程

    React模仿網易云音樂實現一個音樂項目詳解流程

    這篇文章主要介紹了React模仿網易云音樂實現一個音樂項目的詳細流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Electron+React應用打包全流程

    Electron+React應用打包全流程

    本文主要介紹了Electron+React應用打包全流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01

最新評論