antd-style icon indicating copy to clipboard operation
antd-style copied to clipboard

🐛[BUG] antd-styles性能问题: useStyles暴露出的钩子,在组件每次render的时候,都会重新执行styles的计算。

Open guaizi149 opened this issue 1 year ago • 21 comments

尤其是在表格场景,会导致表格非常卡顿。

useTheme()方法每次返回的都是一个可变的theme。 调试了下代码,发现很多地方的context值都没有用memo包裹,最后追踪到antd到theme导出useToken的方法,在每次render的时候也会变化。

image

guaizi149 avatar Jul 26 '24 10:07 guaizi149

没懂,都memo过了,怎么会重新计算?

arvinxx avatar Jul 26 '24 16:07 arvinxx

image 上图中的theme来自于useTheme,而useTheme返回值如下: image 可以看到这里的返回值是没有用useMemo包裹的,所以每次都会变化。如果把这里用useMemo包裹也不行,因为styledTheme每次render都会变化,就这样一层层往上找,,最后追踪到antd到theme导出useToken的方法,在每次render的时候也会变化。

guaizi149 avatar Jul 29 '24 02:07 guaizi149

你的顶层 ConfigProvider 是在哪的?理论上 ConfigProvider 那一层配置过以后应该不会再 re-render 的,所以下层的 useTheme 拿到的值应该都是固化的。 你要不试试看

  const theme = useTheme();

  useWhyDidYouUpdate('Theme', { theme });

看看这个变不变,我之前测下来这都不会 rerender 的

如果会rerender,给一个复现 demo ,我再测一测

arvinxx avatar Jul 29 '24 03:07 arvinxx

仓库地址: https://codesandbox.io/p/github/guaizi149/codesandbox-template-vite-react/main?file=%2Fsrc%2FApp.tsx%3A19%2C5&workspaceId=abf88ce9-7471-4497-a74e-3d25ec1f0ccf

guaizi149 avatar Jul 29 '24 09:07 guaizi149

image 用performance录制,点击按钮,更新count,可以看到Test组件的渲染中调用了updateMemo的hooks,说明useStyles的memo并没有起作用。

guaizi149 avatar Jul 29 '24 09:07 guaizi149

@arvinxx 麻烦问下,这个测下来是确实有性能影响,还是我理解有误?

guaizi149 avatar Aug 06 '24 06:08 guaizi149

@guaizi149 还没来记得看, image

给下权限?我打不开

arvinxx avatar Aug 06 '24 06:08 arvinxx

https://github.com/guaizi149/codesandbox-template-vite-react/tree/main

这个仓库可以打开吧? @arvinxx

guaizi149 avatar Aug 06 '24 06:08 guaizi149

有更新吗?

guaizi149 avatar Sep 04 '24 06:09 guaizi149

@guaizi149 本周会看下

arvinxx avatar Sep 10 '24 18:09 arvinxx

我也遇到了这个问题

zhangtianwei1998 avatar Sep 26 '24 03:09 zhangtianwei1998

+1

Col0ring avatar Sep 26 '24 09:09 Col0ring

https://github.com/guaizi149/codesandbox-template-vite-react/tree/main

这个仓库可以打开吧? @arvinxx

2024/10/24 update

看了你的最新提交 ca88a9e 代码。 如图:

image

你的 <App /> 组件中有一个 state, 并且每次点击按钮都会更新这个 state。

<App /> 组件中有一个 <Test /> 组件。虽然他没有任何 props,但是 <App /> state 变化 re-render 时,<Test /> 也会 re-render。

可以看看这个文章 Before You memo() 了解更多。

如果你不想让 <Test /> 重新渲染,可以使用 React.memo 来包裹 <Test /> 组件。

其次 App 组件中有个 ThemeProvider,同样他也会在每次 App 组件 re-render 时重新渲染。但是 antd-style 是用了 React.memo 包裹的,所以他不会重新渲染。

在用 React.memo 之前可以考虑将 ThemeProvider 提升到外层,App 作为 ThemeProvider 的 children 传递,减少不必要的 re-render。

同理 Test 组件也可以用 children 传递,减少不必要的 re-render。


稍等我再看看 antd-style 通过 createStyles 创建的 useStyles hooks 有没有问题。

就目前看到 props 传递复合类型时是有问题的

Wxh16144 avatar Oct 24 '24 03:10 Wxh16144

看到 props 传递复合类型时是有

Test组件重新渲染是没有问题的。现在的问题是Test重新render的时候,const { styles } = useStyles()这个钩子重新执行了updateMemo,说明useStyles的memo没有起作用,具体原因可以看下开头的叙述。 image

guaizi149 avatar Oct 24 '24 07:10 guaizi149

const { styles } = useStyles()这个钩子重新执行了updateMemo,说明useStyles的memo没有起作用,

createStyles 创建的 hook 是有点问题, 我还在看 ant-desing/cssinjs 逻辑。 感觉上面一层也有点问题。另外你说的 updateMemo 我咋没找到相关代码呢。 是你提供复现仓库吗。 具体我也在看,头大

Wxh16144 avatar Oct 24 '24 08:10 Wxh16144

@Wxh16144 提供的仓库,直接使用performance录制就可以看到updateMemo的调用链。

其实就是我第一条回复中的截图,第二个红框,每次render的时候都执行了。 image

我之前调试过,发现很多地方的context值都没有用memo包裹,我全部使用useMemo包裹后,最终追踪到某一个context值依赖antd到useToken返回值也会在每次render的时候变化。但我刚刚试了最新版本的antd,useToken的返回值已经在每次render的时候不变了。

guaizi149 avatar Oct 24 '24 08:10 guaizi149

但我刚刚试了最新版本的antd,useToken的返回值已经在每次render的时候不变了。

@guaizi149 这是不是意味着如果在 antd-style 里一路 memo 下来,你的问题就解了?

arvinxx avatar Nov 14 '24 15:11 arvinxx

@arvinxx 不好意思,刚看到。 我当时是一路memo下来,最后找到antd的useToken也变化,现在已经不变了。其中context一定要保持不变,不然是不行的。

guaizi149 avatar Nov 26 '24 06:11 guaizi149

@guaizi149 所以现在如果再 memo 的话是不是能解决你的问题?

arvinxx avatar Nov 26 '24 09:11 arvinxx

@arvinxx 之前修改的demo已经被我删掉了。。 之前在表格场景,尤其是虚拟表格,性能影响很严重。现在表格我们已经更换了其他技术栈,所以就没继续研究了~

guaizi149 avatar Nov 26 '24 09:11 guaizi149

尤其是虚拟表格

+1,我的虚拟表方案用的是 react-data-grid,但是看了他们的代码也没发现啥问题,主要是单元格频繁的 mount 和 unmount,单元格中有 antd 组件就会卡, 每个组件都要走 antd cssinjs 那边 好几次,卡没办法解决。

回到 antd-style 来, 其代码也没问题,唯一问题可能就是创建的 useStyles 的方法依赖了外部传进来的变量,如果是引用类型,其每次都会 re-render。 但是场景比较小。 我有一个PR是讲内容进行浅比较。但是也收效甚微。 无奈

Wxh16144 avatar Dec 04 '24 09:12 Wxh16144