useMemo

28 阅读2分钟

上次我分享了关于 useCallback的相关内容,有兴趣的可以去看一下,并且也欢迎大家对我的文章提出问题

组件涉及到的优化方式

为什么我们需要去优化React组件?,React在组件的渲染上会有什么问题?

  • React组件有个特性,在不进行优化处理时父组件更新的时,子组件一定会重新渲染

优化的角度

  • 减少组件的不必要渲染
  • 提高组件的可读性以及减少复杂度,避免出现难以发现的bug

useMemo

useMemo 是一个 React Hook,它在每次重新渲染的时候能够缓存计算的结果。

  • 也就是说通过useMemo后在依赖项不发生变化时,可以不去进行大量非必要的计算,直接得到上次计算的结果
const cachedValue = useMemo(calculateValue, dependencies)

上代码


const filterTodo = (num: number) => {
  console.time("start");
  for (let index = 0; index < num; index++) {
    const elementNode = document.createElement("div");
  }
  console.timeEnd("start");
  return;
};
const Com2 = React.memo((props: any) => {
  console.log("Com2===> 重新渲染了");
  const [com2Data, setCom2Data] = useState(10000);
  
  const [data, setData] = useState(0);
  
  const visibleTodos = filterTodo(com2Data);

  return (
    <>
      <span>Com2的数据: {com2Data}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <br />
      <br />
      <button
        onClick={() => {
          setCom2Data(com2Data+1);
        }}
      >
        点击Com2数据
      </button>
    </>
  );
});

function App() {
  const [appData, setAppData] = useState(0);

  console.log("App===> 重新渲染了");

  const handleFun = useCallback(() => {
    console.log("我是一个函数");
  }, []);

  return (
    <>
      <span>Com2的数据: {com2Data}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <br />
       <span>Com2的数据data: {data}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <br />
      <button
        onClick={() => {
          setCom2Data(com2Data);
        }}
      >
        点击Com2数据
      </button>
      <button
        onClick={() => {
          setCom2Data(com2Data);
        }}
      >
        点击Com2数据
      </button>
    </>
  );
}

export default App;

image.png

  • 点击下appData按钮

image.png 不出意外,这也是我们期待的,因为唯一的props被useCallback包裹

  • 点击下Com2按钮

image.png

也不出意外,是预料之内的,但是每次渲染都会触发filterTodo这里也没啥太大问题,损耗的时间也不多,但是如果大量计算的时候,这里的损耗就要值得关注了

这时候useMemo就该出场了

const Com2 = React.memo((props: any) => {
  console.log("Com2===> 重新渲染了");
  const [com2Data, setCom2Data] = useState(10000);
  const [data, setData] = useState(0);

  const visibleTodos = useMemo(() =>filterTodo(100000),[com2Data]);

  return (
    <>
      <span>Com2的数据: {com2Data}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <br />
       <span>Com2的数据data: {data}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <br />
      <button
        onClick={() => {
          setCom2Data(com2Data);
        }}
      >
        点击Com2Data
      </button>
      <button
        onClick={() => {
          setCom2Data(com2Data);
        }}
      >
        点击Com2Data
      </button>
    </>
  );
});