react的一些性能优化

前端 0 451 0
发表于: 2022-10-19 13:06:24

简介: 暂无~

父组件渲染导致子组件渲染

无优化

import { memo, useState } from 'react';

const ChildCpt = () => {
  console.log('ChildCpt重新渲染了');

  return <div>ChildCpt</div>;
};

const FatherCpt = () => {
  const [count, setCount] = useState(1);

  console.log('FatherCpt重新渲染了');

  return (
    <div>
      <div>count:{count}</div>
      <button onClick={() => setCount(count + 1)}>setCount</button>
      <ChildCpt></ChildCpt>
    </div>
  );
};

export default memo(FatherCpt);

在没有任何优化的情况下,我们每点击一次setCount按钮,都会触发FatherCpt组件渲染,同时带动子组件ChildCpt也跟着渲染,在这个案例里面,很明显子组件是一个很纯的组件,即它没有依赖任何东西,其实它压根就没必要渲染,但是因为父组件渲染了,它也被迫进行了渲染,那么我们接下来就优化一下让ChildCpt,让它不渲染

请别钻牛角尖,说这个场景为什么不把ChildCpt给直接写到FatherCpt里,这只是一个极简的例子,事实上只要是组件就会有渲染问题,和组件本身的大小无关

React.memo优化

最简单的优化就是memo了:

import { memo, useState } from 'react';

const ChildCpt = memo(() => {
  console.log('ChildCpt重新渲染了');
  
  return <div>ChildCpt</div>;
});

const FatherCpt = () => {
  const [count, setCount] = useState(1);

  console.log('FatherCpt重新渲染了');

  return (
    <div>
      <div>count:{count}</div>
      <button onClick={() => setCount(count + 1)}>setCount</button>
      <ChildCpt></ChildCpt>
    </div>
  );
};

export default memo(FatherCpt);

给ChildCpt组件包一层memo后,再次点击setCount按钮,就不会触发ChildCpt组件重新渲染了

缺点:如果用了react的eslint配置,可能 react/display-name 规则会报错,它要求memo里的函数需要有一个函数名,我们可以直接将memo里的箭头函数改成function ChildCpt()就好了,但是看上去就怪怪的,或者我们可以单独的将ChildCpt抽离出去,然后通过import引入进来,这样可能好看点

useMemo

import { memo, useMemo, useState } from 'react';

const ChildCpt = () => {
  console.log('ChildCpt重新渲染了');
  return <div>ChildCpt</div>;
};

const FatherCpt = () => {
  const [count, setCount] = useState(1);
  console.log('FatherCpt重新渲染了');

  return (
    <div>
      <div>count:{count}</div>

      <button onClick={() => setCount(count + 1)}>setCount</button>

      {useMemo(
        () => (
          <ChildCpt></ChildCpt>
        ),
        []
      )}
    </div>
  );
};

export default memo(FatherCpt);

因为ChildCpt不依赖任何数据,因此useMemo的依赖数组就是空数组,这样点击setCount,也不会触发ChildCpt组件重新渲染了

传参导致

无优化

import { memo, useState } from 'react';

const ChildCpt = memo(() => {
  console.log('ChildCpt重新渲染了');

  return <div>ChildCpt</div>;
});

const FatherCpt = () => {
  const [count, setCount] = useState(1);

  console.log('FatherCpt重新渲染了');

  const sayhi = () => console.log('hi');

  return (
    <div>
      <div>count:{count}</div>
      <button onClick={() => setCount(count + 1)}>setCount</button>
      <ChildCpt callback={sayhi}></ChildCpt>
    </div>
  );
};

export default memo(FatherCpt);

每次点击setCount按钮,都会触发ChildCpt重新渲染

传给ChildCpt组件的callback参数,或许ChildCpt会根据它做一些操作,但是,这里是不需要关心的,因为只要父组件FatherCpt重新渲染了,就一定会带动子组件渲染,而且父组件重新渲染的时候,会重新定义一个新的sayhi函数,因此,就会传给callback的sayhi就会被认为是一个新的函数,就会导致ChildCpt重新渲染

useCallback

import { memo, useCallback, useState } from 'react';

const ChildCpt = memo(() => {
  console.log('ChildCpt重新渲染了');

  return <div>ChildCpt</div>;
});

const FatherCpt = () => {
  const [count, setCount] = useState(1);

  console.log('FatherCpt重新渲染了');

  const sayhi = useCallback(() => console.log('hi'), []);

  return (
    <div>
      <div>count:{count}</div>
      <button onClick={() => setCount(count + 1)}>setCount</button>
      <ChildCpt callback={sayhi}></ChildCpt>
    </div>
  );
};

export default memo(FatherCpt);

使用useCallback并且设置了依赖数组为空数组后,再次点击setCount按钮,FatherCpt重新渲染了,但是不会导致ChildCpt重新渲染

React hooks

最后更新于:2022-10-31 18:06:06

欢迎评论留言~
0/400
支持markdown
Comments | 0 条留言
按时间
按热度
目前还没有人留言~