React 性能优化

195 阅读2分钟

使用React.Memo来缓存组件

父组件的每次状态更新都会导致子组件重新渲染,即使传入子组件的状态值发生变化时才会重新渲染,如果传入相同的值,则返回缓存的组件。

提升应用程序性能的一种方法是实现memoization。Memoization是一种优化技术,主要通过存储函数调用的结果,在再次发生相同的输入时返回缓存的结果,以此来加速程序。

export const Header = React.memo((props: IHeaderProps) => {
  const { children } = props;

  return (
    <HStack>
      {!!children && children}
    </HStack>
  );
});

使用useMemo缓存大量的计算

有时候渲染是不可避免的,但如果组件是一个功能组件,重新渲染会导致每次都调用大型计算函数,这是非常消耗性能的,我们可以使用useMemo来记住这个函数的计算结果。这样只有传入的参数有变化,该函数才会重新计算新的结果

  const compressionUri = React.useMemo(
    () => (uri: string) => {
      return `${uri}?imageView2/2/w/300`;
    },
    [],
  );
  
  export const TalkScreen = () => {
  return (
    <Box safeAreaY flex={1} bgColor="gray.100">
         compressionUri('test')
    </Box>
  );
};

避免使用内联对象

使用内联对象时,react会在每次渲染时重新创建对此对象的引用,这回导致接收此对象的组件将其视为不同的对象,因此该组件对于prop的浅层比较始终会返回false导致组件一直重新渲染。许多人使用的内联样式的间接引用,就会使组件重新渲染,可能会导致性能问题。为了解决这个问题,我们可以保证对象只初始化一次,指向相同引用。另外一种情况是传递一个对象,同样会在渲染时创建不同的引用,也有可能导致性能问题,我们可以使用es6扩展运算符将传递对象解构。这样组件接收到的便是基本的props,组件通过浅层比较发现导致接收的props没有变化,则不会重新渲染。

使用React.Fragment避免添加额外的DOM

有些情况下,我们需要在组件中返回多个元素,例如下面的元素,但是在react规定的组件中必须有一个父元素,你可能会这样写,但也会额外创建了不必要的div,这回导致整个应用程序创建许多无用的元素:

  export const TalkScreen = () => {
  return (
        <ChildA />
        <ChildB />
        <ChildC />
  );
};

  export const TalkScreen = () => {
  return (
      <div>
        <ChildA />
        <ChildB />
        <ChildC />
      </div>
  );
};

实际上页面上的元素越多,加载所需的时间就越多。为了减少不必要的加载时间,我们可以使用React.Fragment来避免创建不必要的元素

  export const TalkScreen = () => {
  return (
      <React.Fragment>
        <ChildA />
        <ChildB />
        <ChildC />
      </React.Fragment>
  );
};

当然也可以使用短语法<></>,但是要注意短语法不支持key属性