阅读 73

React中性能优化的手段

在写react的过程中,经常会遇到一个问题,那就是父组件中的数据改变,会引起子组件的重新渲染,看如下代码:

const Father = () => {
  const [data, setData] = useState(0);
  return (
    <div>
      <p>{data}</p>
      <Child />
    </div>
  );
};
复制代码

那么如何解决呢?在这里我记录一下自己的解决办法。所用版本皆为16.8版本,不考虑class的写法。

方法一:

使用React提供的官方api:React.memo。

const Child = React.memo(({ num }) => {
  return <div>{num}</div>;
});

const Father = () => {
  const [data, setData] = useState(0);
  const [num, setNum] = useState(0);
  return (
    <div>
      <p>{data}</p>
      <Child num={num} setNum={setNum} />
    </div>
  );
};
复制代码

这样确实能解决child重复渲染的问题,但是问题又来了,React.memo只能对传入的数据进行浅比较,如果数据嵌套过深,怎么办呢?

答案是给React.memo传第二个参数,通过一些判定条件来决定组件是否渲染。

const Child = React.memo(
  ({ data }) => {
    console.log("child执行");
    return <div>{data.data1.data2.num2}</div>;
  },
  (prevProps, nextProps) => {
    if (prevProps.data.data1.data2.num2 === nextProps.data.data1.data2.num2)
      return true;
  }
);

const Father = () => {
  console.log("father执行");
  const [data, setData] = useState({ data1: { data2: { num1: 1, num2: 2 } } });
  return (
    <div>
      <p onClick={() => setData({ data1: { data2: { num1: 2, num2: 2 } } })}>
        {data.data1.data2.num1}
      </p>
      <Child data={data} />
    </div>
  );
};

export default Father;
复制代码

这样确实能够解决子组件的重复渲染问题,但是我又发现点击事件触发的时候,父组件会反复的执行。

究其原因,原来setState内部比较是使用的Object.is()这个方法,因此父组件重新执行很难避免。

文章分类
前端
文章标签