javascript - 我怎样才能最容易地识别 React 渲染性能的瓶颈?
问题描述
在使用 JSON 查看器时,我遇到了识别渲染性能瓶颈的问题。在元素很少的情况下,它表现良好,但在某一点上它变得非常缓慢。
检查分析器,似乎元素的渲染速度足够快,但我注意到一些我不确定如何解决的问题。
概述
- 该应用程序是一个 JSON 查看器,它允许您一次扩展/最小化所有元素以及单个元素。
- 元素很少,性能很好,但随着元素数量的增加,性能似乎急剧下降。
- 在使用 React DevTools 分析我的对象过滤器方法
performance.now()
以及检查渲染时间时,这些数字看起来还不错。我可能解释错了。 - 我尝试过
React.memo()
在无状态元素上使用(尤其是最常呈现的组件的键/值),但它似乎并没有显着提高性能。诚然,我不确定我是否充分理解了记忆 React 组件背后的推理以有效地实现这一点。
执行
- 目前,我的应用程序将数据加载到父级中,该父级馈送到使用递归元素加载 JSON 树的组件中。
- 从 URL 加载 JSON 提要会更改父组件的状态,该状态使用辅助方法进行过滤,该方法使用输入字段中的值。
问题
有两个功能可以重现(不是很大)JSON 文档的缓慢响应时间:
- 全部展开按钮
- 过滤查询的前几个按键
在当前的实现中,过滤和扩展都触发了display: none
子元素的变化,这种行为让我相信我在处理这个用例时效率低下。
复制步骤
代码可在此处获得:https ://codesandbox.io/s/react-json-view-4z348
这里有一个生产版本(没有更好的表现):https ://csb-4z348.vercel.app/
要重现此问题,请使用 Expand All 功能(过滤器输入旁边的加号)和一些过滤器输入。
然后,尝试加载包含更多元素的 JSON 提要(您可以在我的GitHub API 提要上进行测试)并尝试过滤/扩展所有元素。注意主要的性能影响。
我注意到了什么
- 在记录 useEffect 时,最小化似乎导致重新渲染的次数是扩展全部的 2 倍。
- 随着过滤器输入变得更加具体,性能(逻辑上)随着渲染的元素减少而提高。
问题
虽然我希望为这个特定案例朝着正确的方向轻推,但我最好奇的是如何最好地确定导致这些性能问题的原因。
我已经研究过窗口化输出,但这不是我的第一选择,而且我很确定我做错了什么,而不是因为渲染了太多元素。
感谢您的宝贵时间,并提前感谢您提供的任何提示!
解决方案
看来我已经回答了我自己的问题。问题是由于在我的子组件中使用 UUID 作为关键道具而导致的协调问题,这导致它们在每次最小化状态更改时重新渲染。从文档:
密钥应该是稳定的、可预测的和唯一的。不稳定的键(如 Math.random() 产生的键)会导致许多组件实例和 DOM 节点被不必要地重新创建,这可能会导致性能下降和子组件中的状态丢失。
我会将这些步骤留给遇到此问题的其他人。
在(太长时间)在性能分析器中挖掘之后,我注意到每次我最小化或扩展元素时,每个孩子都会再次被安装。在通过更具体的查询咨询 Google 后,我发现了这篇博文,并意识到我犯了这个公然的性能错误。
一旦我找到了问题的根源,我就找到 了许多 其他的 参考资料。
修复关键道具后,最小化/扩展全部的交互时间加快了约 60%。
最后,我记住了一些与即时过滤器相关的其他组件,最后它似乎暂时表现得和我想要的一样好。
感谢在此期间查看此内容的任何人,我希望它对任何可能遇到此问题的人有所帮助。
推荐阅读
- css - 在 CSS 中使用标题的目的是什么?
- salesforce-communities - 从 Salesforce 中的另一个社区用户登录时如何创建社区用户?
- javascript - 底部彩条的滑块悬停效果不起作用
- sql - SQL Query 通过加入表来获取总和
- android - java.lang.NullPointerException:尝试在 Android 10 上调用虚拟方法“java.lang.String java.io.File.getName()”
- python - 来自给定分布函数的随机数生成器
- azure - 如何使用 Azure Function 在 Azure 文件共享中解压缩文件?
- python - 如何计算任何 CSV 数据的采样率?
- ios - 如何更改状态栏和滑动栏部分的颜色?
- java - 使用spring验证:在包含@valid和验证注释的restful服务中没有返回消息