常见的 React 性能错误
React.memo
内联函数
使用回调
性能优化是软件开发人员面临的挑战之一。
当你在数月甚至数年后才开始优化应用程序时,这无疑是一个巨大的负担。实际上,我们不得不以某种方式回顾代码,以优化应用程序的性能。
但是在编写代码时遵循一些性能优化和最佳实践可以最大限度地减轻负担。
同时优化也是一把“双刃剑”。
性能相关的变化如果应用不当甚至会损害性能。
在这里我将解释一些我在 React 应用程序中看到和遇到的事情。
React.memo
如果你使用 React,你就会注意到这个特殊的 HOC。它主要用于记忆整个组件。
这是一个带有 memoized 的子组件,它接收 handleOnClick 作为 props 。因此,根据 memoized 逻辑,只有当任何 props 发生变化时,该组件才应该重新渲染。这就是React.memo 的工作原理,但等等,让我们创建一个父组件并检查一下。
完美,因此在子组件中的每个 onClick 触发期间,父状态值都会发生变化,但子组件中收到的 props 不会改变,因此由于我们已经记住了,子组件不会重新渲染。
但是等一下,真正的问题就在这里,如果您在任何编辑器中尝试上述代码,或者下面有一个 codesandbox,您会看到React.memo已损坏!即使 prop 相同,子组件也会因每次状态更改而重新渲染。
React.memo 🤯有什么问题吗?
不行!每次父组件重新渲染时,都会创建一个新的handleOnClick函数实例。因此,这会导致记忆机制失效,每次都重新渲染子组件。
因此,如果您只是用React.memo包装子组件,那么就无法保证我只会记住并工作。
但是很酷的钩子 useCallback 可以帮到你!将 handleClick 函数包装在 useCallback 钩子中并尝试相同的代码,React.memo将按预期工作。
但我想说,上面的那个也被高估了,我会在文章后面解释为什么
在这里玩
不要在 props 频繁变化的组件中使用React.memo ,这将导致大量的计算。
内联函数
return (
<div>
<button onClick={()=>setState(state+1)}>Increment</button>
</div>
)
每当开发人员捕获此代码时,每个人(包括我自己🤩)都会更新以下代码,就像!
const handleIncrement = () => setState(state+1);
return (
<div>
<button onClick={handleIncrement}>Increment</button>
</div>
)
是的,我已经解决了大坝性能问题,我将在灯塔中获得 100 的性能分数。
但在这种情况下内联实际上是没问题的!如果你有疑问,可以尝试一下这个
useEffect(()=>{
console.log('正在执行')
},[setState])
如果您使用 eslint,则不能在 useEffect 中使用用户定义的函数,它会发出警告!但上面的代码可以正常工作,因为 react 很聪明,在这种情况下它知道 setState 永远不会改变!。
注意❌:如果没有箭头函数,则不应调用内联函数
<button onClick={handleIncrement()}>Increment</button>
❌这可能会导致你的代码陷入无限循环
使用回调
在这里使用这个钩子有意义吗?🤔
这是您在使用 useCallback 和 useMemo 等性能钩子之前应该考虑的第一个问题。
上面使用的例子也被高估了,不要混淆。上面的例子只是为了解释事情是如何运作的!但想象一下,子组件只是重新渲染了一个“div”和一个“p”标签。这里没有昂贵的计算,也没有任何影响 CPU 的操作,那么为什么这里要使用 useCallback 呢?
如果子组件包含大量数据或大量计算,则可以使用 useCallback 包装传递的回调函数。
记住,即使 useCallback() 返回的是同一个函数对象,每次重新渲染时都会重新创建内联函数,而 useCallback() 只是跳过了它而已。所以,与此处使用 useCallback 相比,重新渲染的换向更少!
同样的规则也适用于useMemo
使用我制作的辅助网站 [kit] 来管理您的“在家工作”🏡 问题(https://dev.to/karthick3018/manage-work-from-home-effectively-using-wfh-kit-6bc)
在github上查看我的开发项目
在 twitter上关注我 在linkedIn
上与我联系在 codepen上查看我的样式
感谢您的时间!祝您
编程愉快!继续分享,
注意安全!