原文地址:《Snappy UI Optimization with useDeferredValue》 - 使用 useDeferredValue 进行快速UI优化
NOTE
- 指定低优先级,延迟更新
- 使用
useDeferredValue
时,子组件需要memo
useDeferredValue
的值并不一定必须是state
- 使用
useDeferredValue
可以获取UI更新中的状态,可以像用户明确展示UI发生变化,正在更新- React 19 中
useDeferredValue
可以指定一个默认值,加快初始渲染速度
这篇文章的标题是《使用 useDeferredValue 优化 UI 性能》,作者 Josh W. Comeau 讨论了 React 中一个强大但鲜为人知的工具:useDeferredValue
。这个钩子可以在特定情况下对用户体验产生巨大的影响。
引言
作者介绍了 useDeferredValue
,并分享了如何使用它来修复他的博客上的一个性能问题。他发现在低端设备上的性能提升感觉像在使用黑魔法。
问题
文章通过作者之前发布的一个工具——Shadow Palette Generator(阴影调色板生成器)来说明问题。这个工具允许用户通过滑动滑块和其他控件来设计自己的阴影集,并将 CSS 代码提供给用户复制粘贴到他们自己的应用中。
问题在于,UI 中的控件旨在提供即时反馈,即当用户拖动滑块时,UI 会每秒重新渲染数十次。对于大多数设备来说,浏览器无法足够快地完成这些操作,导致界面变得卡顿。
不完美的解决方案
作者最初使用“节流”技术来解决这个问题,将组件的重新渲染限制为每200毫秒一次。虽然这比之前更好,但仍然不完美。它给用户一种延迟的感觉,而且不考虑不同设备的性能差异。
介绍 useDeferredValue
useDeferredValue
是一个 React 钩子,允许我们将 UI 分为高优先级和低优先级区域。它的工作原理是允许 React 在重要事件发生时中断自身。
示例
作者通过一个简单的例子来解释 useDeferredValue
的工作原理。在这个例子中,有一个名为 count
的状态变量,可以通过点击按钮来递增。ImportantStuff
代表 UI 的高优先级部分,我们希望它在 count
变化时立即更新。SlowStuff
代表 UI 的低优先级部分。
工作原理
当 count
状态变化时,App
组件会立即重新渲染,但 deferredCount
(由 useDeferredValue
提供)并没有改变,仍然是之前的值。这意味着 SlowStuff
接收到的属性与上一次渲染时完全相同。如果它使用了 React.memo()
进行了记忆化,它就不会重新渲染,因为 React 已经知道将产生什么内容。
注意事项
useDeferredValue
仅在慢速/低优先级组件被React.memo()
包装时才有效。- 与多个状态变量一起使用
useDeferredValue
时,可以推迟派生值的渲染,例如在渲染期间生成的 CSS 代码块。
加载指示
在某些情况下,我们可能希望向用户明确指出 UI 的某些部分已经过时,以便他们知道正在进行重新计算。
初始渲染加速
React 19 的 beta 版本为 useDeferredValue
带来了一个新的能力:可以指定一个初始值。这将允许我们潜在地加速初始渲染。
结果
作者展示了使用 useDeferredValue
钩子后的最终结果:一切都非常流畅。即使是在低端设备上,性能也有了显著提升。
结论
useDeferredValue
可能看起来复杂,但如果你有正确的思维模型,它实际上并不可怕。作者通过这篇文章帮助读者理解了 useDeferredValue
的工作原理,并展示了如何使用它来显著提高应用程序的性能。