如何在性能损失很小的情况下包装 React 组件?

IT技术 reactjs performance material-ui
2021-05-25 15:19:54

我的团队使用 React MaterialUI库。为了提供一致的 UI Pattern 并方便我们自定义 MaterialUI 的组件,我们将每个 MaterialUI 的组件包装在我们自己的组件中。例如:

const style = {} // our project custom style for ListItemText
const OurListItemText = ({primary, secondary, classes}: Props) => (
  <MuiListItemText
    primary={primary}
    secondary={secondary}
    className={classes.text}
  />
) // we only expose primary and secondary props of the original MuiListItemText.
// Team members are blocked from customising other MUIListItemText's props

export default withStyles(styles)(OurListItemText)

MuiListItemText是原始MaterialUI的组件,而OurListItemText是我们的包装器组件。在我们的项目中, OurListItemText允许使用。

正如上面的代码片段,OurListItemText除了将 props 转发到MuiListItemText. 但是,这对性能影响很大:

react火焰图

ListItemText顶部的栏来自 ,OurListItemText而下方的来自MuiListItemText如果我们MuiListItemText直接使用,它可能会快约 50%(我们已经尝试过),这在我们有 100 时很明显ListItemText删除withStylesHOC 会有所改善,但并不显着。

ListItemText这只是一个例子,我们在其他包装组件上也有类似的性能问题。Typography上图中的2是另一对 our-wrapper-component 和 MUI's-original-component)

如何提高那些简单的 props-forwarding-components 的性能?

2个回答

包装一个 React 组件会增加一个额外的完整 React 生命周期级别(即需要安装包装器)。有没有可能避免这种情况?

您可以通过避免 JSX 并直接调用函数来避免生命周期。
例如。

{Component({ data: 1, children: 'Hello' })}

代替

<Component data={1}>Hello</Component>

这篇博文声称通过他们的测试用例实现了 45% 的速度提升。

但是,此语法可能不那么可读/可理解。

Dan Abramov 关于这个问题的一些引述

我们正在 Prepack 的上下文中研究这样的优化,但在接下来的几个月内没有任何东西可以立即使用。在一两年内,我们可能会有所收获。

请注意,除非您要创建数千个元素,否则性能差异不会很明显。此外,除非您的组件非常扁平和简单,否则这种优化的“纯胜利”在实践中可能不太相关。

我不会等待 Prepack 进行优化,因为时间线不确定,而且优化结果可能与此不同。

至于性能改进的意义,这取决于您的项目,唯一可以确定的方法是亲自尝试并看到改进。

如果您想要原始性能 - 不要包装 ListItem,而是编写您的替代品

列表项源没有任何额外的依赖项,因此 Ctrl-C、Ctrl-V 将起作用

然后根据您的需要进行调整,删除您不需要的代码等...

这将保证最大可能的性能


不利的一面——支持成本会增加。