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

減少react組件不必要的重新渲染實(shí)現(xiàn)方法

 更新時(shí)間:2023年01月09日 09:50:51   作者:糖瓶  
這篇文章主要為大家介紹了減少react組件不必要的重新渲染實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

什么是重新渲染

react重新渲染是當(dāng)你的組件已經(jīng)渲染在屏幕上,由于數(shù)據(jù)狀態(tài)變化,又重新觸發(fā)了組件的渲染。重新渲染是正?,F(xiàn)象,但有時(shí)由于自身代碼問題造成不必要的重新渲染。

不必要的重新渲染

由于錯(cuò)誤的代碼引發(fā)組件的重新渲染。例如:與react組件本身無關(guān)的狀態(tài)變化引起的組件的重新渲染。雖然react組件重新渲染了,但由于渲染很快,通常用戶并不會(huì)感知到。但如果重新渲染發(fā)生比較復(fù)雜的組件上,可能會(huì)導(dǎo)致界面卡頓,甚至造成長(zhǎng)時(shí)間的卡死現(xiàn)象。

react組件重新渲染情況

組件的重新渲染分為以下幾種情況:

state變化

count變化會(huì)引起組件的重新渲染。

const App = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count+1)
  }
  return <div onClick={handleClick}>{count}</div>
}

父組件的重新渲染

當(dāng)組件的父組件重新渲染時(shí),該組件必定重新渲染。一般情況下子組件的渲染不會(huì)觸發(fā)父組件的渲染。

實(shí)際上props變化也是由于父組件狀態(tài)變化引起的,只要父組件重新渲染,子組件不管props有沒有變化都會(huì)重新渲染。(沒有使用優(yōu)化時(shí))

import { useState } from "react";
const Child = () => {
  console.log("子組件重新渲染");
  const [childCount, setChildCount] = useState(0);
  const handleChildClick = () => {
    setChildCount(childCount + 1);
  };
  return (
    <>
      <div onClick={handleChildClick}>Child {childCount}</div>
    </>
  );
};
export default function StateChange() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };
  console.log("父組件重新渲染", count);
  return (
    <div>
      <div onClick={handleClick}>parent {count}</div>
      <Child />
    </div>
  );
}

context變化

當(dāng)context的Provider提供的值放生變化,所有使用該context的組件都將重新渲染。

import { createContext, useState, useContext, useMemo } from "react";
const Context = createContext({ val: 0 });
const Provider = ({ children }) => {
  const [val, setVal] = useState(0);
  const handleClick = () => {
    setVal(val + 1);
  };
  const value = useMemo(() => {
    return {
      val: val
    };
  }, [val]);
  return (
    <Context.Provider value={value}>
      {children}
      <button onClick={handleClick}>context change</button>
    </Context.Provider>
  );
};
const useVal = () => useContext(Context);
const Child1 = () => {
  const { val } = useVal();
  console.log("Child1重新渲染", val);
  return <div>Child1</div>;
};
const Child2 = () => {
  const { val } = useVal();
  console.log("Child2重新渲染", val);
  return <div>Child2</div>;
};
export default function ContextChange() {
  return (
    <Provider>
      <Child1 />
      <Child2 />
    </Provider>
  );
}

在組件內(nèi)創(chuàng)建組件

?:這種做法非常消耗性能。當(dāng)組件重新渲染,內(nèi)部組件都會(huì)重新mount。這種做法容易導(dǎo)致很多bug出現(xiàn)。

import { useState, useEffect } from "react";
const Component = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  const InComponent = () => {
    console.log("內(nèi)部組件重新渲染");
    useEffect(() => {
      console.log("內(nèi)部組件重新mount");
    }, []);
    return <div>inComponent</div>;
  };
  return (
    <>
      <button onClick={onClick}>點(diǎn)我</button>
      <InComponent />
    </>
  );
};
export default function ComInComponent() {
  return (
    <>
      <Component />
    </>
  );
}

一些減少重新渲染的方法

useState初始值使用函數(shù)形式

看一個(gè)例子:useState的初始值經(jīng)過a + 1計(jì)算得到: 此時(shí)的useState的參數(shù)是一個(gè)函數(shù)執(zhí)行,也就是一個(gè)值

import { useState } from "react";
function getInitState() {
  console.count("獲取初始化的值");
  const a = 1;
  return a + 1;
}
const App = () => {
  const [value, setValue] = useState(getInitState());
  const onChange = (event) => setValue(event.target.value);
  return <input type="text" value={value} onChange={onChange} />;
};
export default App;

當(dāng)我們?cè)趇nput中繼續(xù)輸入,可以看到getInitState的console次數(shù):

當(dāng)我們把useState第一個(gè)參數(shù)改為函數(shù)時(shí):(該函數(shù)會(huì)自動(dòng)調(diào)用)

import { useState } from "react";
function getInitState() {
  console.count("獲取初始化的值");
  const a = 1;
  return a + 1;
}
const App = () => {
  const [value, setValue] = useState(getInitState);
  const onChange = (event) => setValue(event.target.value);
  return <input type="text" value={value} onChange={onChange} />;
};
export default App;

該函數(shù)只會(huì)在初始化的時(shí)候調(diào)用一次:

重新組織組件結(jié)構(gòu)

提取單獨(dú)的組件,獨(dú)自維護(hù)自己的狀態(tài),防止發(fā)生不必要的渲染。

import { useState } from "react";
const BigComponent = () => {
  console.log("一個(gè)非常復(fù)雜的大組件:渲染了");
  return <div>BigComponent</div>;
};
const AllComponent = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
      <BigComponent />
    </>
  );
};
const ButtonComponent = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
    </>
  );
};
const SplitComponent = () => {
  return (
    <>
      <ButtonComponent />
      <BigComponent />
    </>
  );
};
const App = () => {
  return (
    <>
      <p>AllComponent是沒有重新組織的組件</p>
      <AllComponent />
      <hr />
      <p>SplitComponent是重新組織劃分的組件, 不會(huì)觸發(fā)大組件BigComponent的渲染</p>
      <SplitComponent />
    </>
  );
};
export default App;

巧用props.children

利用props.children 來減少不必要的重復(fù)渲染。

import { useState } from "react";
const BigComponent = () => {
  console.log("一個(gè)非常復(fù)雜的大組件:渲染了");
  return <div>BigComponent</div>;
};
const AllComponent = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
      <BigComponent />
    </>
  );
};
const ComponentWithChildren = ({ children }) => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
      {children}
    </>
  );
};
const SplitComponent = () => {
  return (
    <ComponentWithChildren>
      <BigComponent />
    </ComponentWithChildren>
  );
};
const App = () => {
  return (
    <>
      <p>AllComponent是沒有重新組織的組件</p>
      <AllComponent />
      <hr />
      <p>
        SplitComponent是巧用了children的組件, 不會(huì)觸發(fā)大組件BigComponent的渲染
      </p>
      <SplitComponent />
    </>
  );
};
export default App;

把組件當(dāng)成props傳遞

把組件當(dāng)成props傳遞給其他組件,也可以減少渲染。(與children類似)

import { useState } from "react";
const BigComponent = () => {
  console.log("一個(gè)非常復(fù)雜的大組件:渲染了");
  return <div>BigComponent</div>;
};
const AllComponent = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
      <BigComponent />
    </>
  );
};
const ComponentWithProps = ({ comp }) => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  return (
    <>
      <p>重新渲染次數(shù): {state}</p>
      <button onClick={onClick}>點(diǎn)我</button>
      {comp}
    </>
  );
};
const comp = <BigComponent />;
const SplitComponent = () => {
  return (
    <>
      <ComponentWithProps comp={comp} />
    </>
  );
};
const App = () => {
  return (
    <>
      <p>AllComponent是沒有重新組織的組件</p>
      <AllComponent />
      <hr />
      <p>
        SplitComponent是把組件當(dāng)成props傳遞, 不會(huì)觸發(fā)大組件BigComponent的渲染
      </p>
      <SplitComponent />
    </>
  );
};
export default App;

React.memo

memo 減少重復(fù)渲染,只要子組件的props沒有改變(淺比較)。

import { useState, memo } from "react";
const Child = () => {
  console.log("子組件重新渲染");
  return (
    <>
      <div>Child</div>
    </>
  );
};
const MemoChild = memo(Child);
export default function ReactMemo() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <div onClick={handleClick}>parent {count}</div>
      <MemoChild />
    </div>
  );
}

如果props是一個(gè)object, array 或者 function,memo必須配合useMemo來緩存,單獨(dú)使用都不起作用。

當(dāng)然也可以單獨(dú)使用useMemo緩存整個(gè)組件。

import React, { useState, useMemo } from "react";
const Child = ({ value }) => {
  console.log("Child重新渲染", value.value);
  return <>{value.value}</>;
};
const values = [1, 2, 3];
const UseMemp = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    setState(state + 1);
  };
  // 使用useMemo緩存組件
  const items = useMemo(() => {
    return values.map((val) => <Child key={val} value={{ value: val }} />);
  }, []);
  return (
    <>
      <button onClick={onClick}>點(diǎn)我 {state}</button>
      <br />
      {items}
    </>
  );
};
export default UseMemp;

useCallback

函數(shù)傳遞可以使用useCallback來緩存函數(shù)。

key值

在循環(huán)數(shù)組時(shí),有人使用index作為key,可以這樣做,但是你要保證你的數(shù)組是靜態(tài)的,沒有新增,刪除,插入,排序等情況,否則不能使用index作為key。

完整的代碼:

codesandbox.io/s/hidden-me…

參考

reactjs.org/docs/hooks-…

medium.com/@guptagarud…

以上就是減少react組件不必要的重新渲染實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于減少react組件重新渲染的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在React頁面重新加載時(shí)保留數(shù)據(jù)的實(shí)現(xiàn)方法總結(jié)

    在React頁面重新加載時(shí)保留數(shù)據(jù)的實(shí)現(xiàn)方法總結(jié)

    在React頁面重新加載時(shí)保留數(shù)據(jù),可以通過多種方法來實(shí)現(xiàn),常見的方法包括使用瀏覽器的本地存儲(chǔ)(Local Storage 或 Session Storage)、URL參數(shù)、以及服務(wù)器端存儲(chǔ)等,本文給大家總結(jié)了一些具體實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-06-06
  • 詳解react內(nèi)聯(lián)樣式使用webpack將px轉(zhuǎn)rem

    詳解react內(nèi)聯(lián)樣式使用webpack將px轉(zhuǎn)rem

    這篇文章主要介紹了詳解react內(nèi)聯(lián)樣式使用webpack將px轉(zhuǎn)rem,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • concent漸進(jìn)式重構(gòu)react應(yīng)用使用詳解

    concent漸進(jìn)式重構(gòu)react應(yīng)用使用詳解

    這篇文章主要為大家介紹了concent漸進(jìn)式重構(gòu)react應(yīng)用的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • styled-components?性能詳解

    styled-components?性能詳解

    這篇文章主要為大家介紹了styled-components?的性能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能

    react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能

    這篇文章主要介紹了react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序,本文結(jié)合實(shí)例代碼講解react-dnd是如何實(shí)現(xiàn),代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • 代碼解析React中setState同步和異步問題

    代碼解析React中setState同步和異步問題

    前端框架從MVC過渡到MVVM。從DOM操作到數(shù)據(jù)驅(qū)動(dòng),一直在不斷的進(jìn)步著,本文給大家介紹React中setState同步和異步問題,感興趣的朋友一起看看吧
    2021-06-06
  • react實(shí)現(xiàn)每隔60s刷新一次接口的示例代碼

    react實(shí)現(xiàn)每隔60s刷新一次接口的示例代碼

    本文主要介紹了react實(shí)現(xiàn)每隔60s刷新一次接口的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 使用react完成點(diǎn)擊返回頂部操作

    使用react完成點(diǎn)擊返回頂部操作

    本文主要介紹了使用react完成點(diǎn)擊返回頂部操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 適用于React?Native?旋轉(zhuǎn)木馬應(yīng)用程序介紹

    適用于React?Native?旋轉(zhuǎn)木馬應(yīng)用程序介紹

    這篇文章主要介紹了適用于React?Native?旋轉(zhuǎn)木馬應(yīng)用程序介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • React使用highlight.js Clipboard.js實(shí)現(xiàn)代碼高亮復(fù)制

    React使用highlight.js Clipboard.js實(shí)現(xiàn)代碼高亮復(fù)制

    這篇文章主要為大家介紹了React使用highlight.js Clipboard.js實(shí)現(xiàn)代碼高亮復(fù)制功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評(píng)論

五家渠市| 正安县| 阿城市| 武陟县| 大足县| 秦安县| 平凉市| 曲水县| 通河县| 马公市| 射阳县| 安远县| 鹤峰县| 清苑县| 开阳县| 邳州市| 萍乡市| 颍上县| 连平县| 和平县| 万山特区| 孙吴县| 阜新市| 浦北县| 交口县| 兰考县| 苏尼特左旗| 阿拉善右旗| 毕节市| 个旧市| 文水县| 通州市| 开原市| 全椒县| 荥经县| 嘉义市| 修文县| 文山县| 博乐市| 承德县| 萨嘎县|