【问题标题】:MUI - Slow makeStyles if using props in methodsMUI - 如果在方法中使用道具,makeStyles 会变慢
【发布时间】:2021-10-23 06:50:50
【问题描述】:

我在渲染大量组件时遇到问题,其中每个组件都有一个useStyles。我们希望组件道具影响样式,所以我们结合道具和主题设置。工作正常,除了它非常慢而且我将其缩小到它是由 makeStyles 中的 prop 方法引起的。

实际上是否使用该类并不重要。如果所有类都是静态的,它会很快,但如果我添加一个未使用的类作为方法,它会很慢。道具也无所谓,如果我添加test: { fontWeight: () => 'bold' } 它会再次变慢。

确实很奇怪。我正在使用 Material UI ^4.11.0。不是最新版本的 v4。漏洞?有人听说过这个吗?有人有更好的解决方案来添加基于道具的样式并同时使用主题吗?任何人都通过使用 useMemo 或任何东西获得了性能改进? (我试过没有效果)。

 const useStyles = makeStyles(({ typography }) => ({
  fontFamily: {
    fontFamily: ({ fontFamily }: any) => fontFamily,
  },
  fontFamilySecondary: {
    fontFamily: typography.fontFamilySecondary,
  },
  ...filterCustomVariants(typography),
  bold: {
    fontWeight: typography.fontWeightBold,
  },
  boldScondary: {
    fontWeight: typography.fontWeightBoldSecondary,
  },
  italic: {
    fontStyle: "italic",
  },
  thisIsNotEvenUsed: {
    fontWeight: () => {
      console.log("Running running running") // Runs many times anyway!
      return "bold"
    },
  },
}))

以及实现:

const styleProps = { fontFamily: fontFamily }
const classes = useStyles(styleProps)

编辑:这是一个 CodeSandbox,它使用最新的 MUI v4 显示了这种行为,并且没有我的应用程序复杂性:https://codesandbox.io/s/black-monad-tr05l?file=/src/App.tsx

【问题讨论】:

  • 看来您使用 makeStyles 的方式有误。类似问题:stackoverflow.com/q/69608311/9449426
  • @NearHuscarl 你是对的,我确实用错了方法。我现在在上面更新了我的代码示例。恐怕它并没有让事情变得更快,而且 thisIsNotEvenUsed 类仍然运行数百次,即使它没有使用的类。
  • 您的代码中一定有其他问题。你能添加使用useStyles的整个组件吗?
  • @NearHuscarl 不,在这里看看我的沙盒链接:codesandbox.io/s/black-monad-tr05l?file=/src/App.tsx

标签: reactjs performance material-ui


【解决方案1】:

这不是错误,makeStyles 在 v5 中的行为方式相同。使用回调的动态样式是JSS feature。但是众所周知,JSS 的动态性能非常糟糕(有关更多详细信息,请参阅performance 部分,它比情感慢大约 6 倍)。这也是 MUI 团队决定在 v5 中弃用它转而使用大量动态样式的情感的原因之一。

是的,即使您没有在内部传递任何内容并且不使用classes 对象,它也会始终调用回调。它遍历样式对象和当您调用useStyles 时找到的invoke every callbacks。有关makeStyles 工作原理的更多详细信息,我建议您阅读Ryan 的this 回答。

const useStyles = makeStyles({
  thisIsNotEvenUsed: {
    fontWeight: () => {
      console.log("Running running running"); // Runs many times anyway!
      return "bold";
    }
  }
});
const unusedClasses = useStyles(); // generate the styles

有一些策略可以提高性能。最简单的一种(视情况而定)是升级到 v5 以利用情感及其高效生成动态样式的能力。另一种方法是使用内联样式:

<Typography style={{ fontWeight: props.fontWeight }}>

但是如果你不想用内联样式污染你的组件,你仍然可以使用 makeStyles 使用“样式注入”方法,通过在容器中创建一个嵌套样式来容纳大量元素(@ 987654335@, List, Stack...)

const useStyles = makeStyles({
  root: {
    "& MuiTypography-root": {
      fontWeight: () => 'bold'
    }
  }
});
<div className={classes.root}>
  {[...Array(100)].map((_, index) => {
    return <Text key={`text_${index}`}>Text Component</Text>;
  })}
</div>

【讨论】:

  • 这么好的答案!真的没想到。非常感谢您的见解。很明显,我们将来想要样式化的组件,但对于大型项目来说这是一项艰巨的任务。样式注入是一个很好的建议,我会直接尝试。我可能会使用更多的内联样式,并从在各处多次使用的组件开始。
  • 这仍然很慢并且运行很多,所以我们将使用内联样式。 "& > .thisIsNotEvenUsed": { fontWeight: () => { console.log("Running running running") // 反正运行了很多次!返回“粗体”}, },
  • @TonyGustafsson 你是嵌套列表还是容器太多?如果在容器中应用动态样式,则每次渲染仅生成一次。在代码框里,如果你点击渲染按钮强制应用重新渲染,它只会打印一次消息。
猜你喜欢
  • 2019-09-30
  • 2021-09-30
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2021-12-02
  • 2021-12-09
相关资源
最近更新 更多