You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI v4 makeStyles中使用props方法引发大量组件渲染变慢问题咨询

问题确认

这个是Material UI v4的已知设计缺陷,并非代码逻辑导致的Bug。v4版本makeStyles的底层逻辑只要检测到样式定义中存在任意函数类型的样式值,每次调用useStyles传参时,都会全量遍历所有样式规则、执行所有规则函数,无论对应的样式类是否被组件实际使用,这就是你观测到未使用的样式函数也会反复执行、渲染变慢的核心原因。该问题受限于v4的样式架构,没有在后续v4小版本中彻底修复,直到v5版本更换了样式解决方案才完全解决。

可行优化方案(均支持props控制样式、读取theme配置)

方案1:拆分静态与动态样式规则

把不需要props控制的静态样式,和需要props控制的动态样式拆分到不同的makeStyles实例中,静态样式的makeStyles完全不包含函数类型定义,避免不必要的全量遍历:

// 静态样式,无任何函数定义,性能无损耗
const useStaticStyles = makeStyles(({ typography }) => ({
  fontFamilySecondary: {
    fontFamily: typography.fontFamilySecondary,
  },
  bold: {
    fontWeight: typography.fontWeightBold,
  },
  boldScondary: {
    fontWeight: typography.fontWeightBoldSecondary,
  },
  italic: {
    fontStyle: "italic",
  },
}))

// 仅包含需要props控制的动态样式,遍历规则数量极少,性能损耗可忽略
const useDynamicStyles = makeStyles(() => ({
  fontFamily: {
    fontFamily: ({ fontFamily }: any) => fontFamily,
  },
}))

// 组件内调用
const staticClasses = useStaticStyles()
const styleProps = useMemo(() => ({ fontFamily }), [fontFamily])
const dynamicClasses = useDynamicStyles(styleProps)
// 合并类名使用即可
const classes = {...staticClasses, ...dynamicClasses}

方案2:用类名切换替代props传参

如果动态样式的取值范围有限,提前定义好所有可选的静态样式类,配合clsx工具根据props切换类名,完全避免在makeStyles中写函数,性能最优:

import clsx from 'clsx'

const useStyles = makeStyles(({ typography }) => ({
  fontSans: { fontFamily: typography.fontFamilySans },
  fontSerif: { fontFamily: typography.fontFamilySerif },
  fontMono: { fontFamily: typography.fontFamilyMono },
  // 其余静态样式
}))

// 组件内调用
const classes = useStyles()
const textClass = clsx({
  [classes.fontSans]: fontFamily === 'sans',
  [classes.fontSerif]: fontFamily === 'serif',
  [classes.fontMono]: fontFamily === 'mono',
})

方案3:使用MUI v4内置的styled API

styledAPI的样式计算是和组件绑定的,不会全量遍历无关规则,性能远高于带函数的makeStyles:

import { styled } from '@material-ui/core/styles'

const CustomText = styled('div')(({ theme, fontFamily }) => ({
  fontFamily: fontFamily || theme.typography.fontFamily,
  fontWeight: theme.typography.fontWeightBold,
  // 其余样式
}))

// 组件内使用
<CustomText fontFamily={fontFamily}>内容</CustomText>

补充优化点

  • 传给useStyles的props必须用useMemo缓存,只有依赖的属性变化时才重新生成对象,避免不必要的样式重计算,这也是你之前单独用useMemo没生效的常见原因
  • 尽量减少makeStyles中函数类型规则的数量,能抽成静态类的都抽成静态类
  • 如果业务允许升级依赖,推荐升级到MUI v5版本,v5的样式方案从底层解决了这个性能问题

内容的提问来源于stack exchange,提问作者Tony Gustafsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 12:15:04