使用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属性