使用 react-hooks 在每次渲染上创建处理程序的性能损失 [英] Performance penalty of creating handlers on every render with react-hooks

查看:151
本文介绍了使用 react-hooks 在每次渲染上创建处理程序的性能损失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前对新的 react hooks API 的用例感到非常惊讶以及你可以用它做什么.

在试验过程中出现的一个问题是,在使用 useCallback 时总是创建一个新的处理函数只是为了将其丢弃是多么昂贵.

考虑这个例子:

const MyCounter = ({initial}) =>{const [count, setCount] = useState(initial);const增加 = useCallback(() => setCount(count => count + 1), [setCount]);const 减少 = useCallback(() => setCount(count => count > 0 ? count - 1 : 0), [setCount]);返回 (<div className="计数器"><p>计数为{count}.</p><button onClick={decrease} disabled={count === 0}>- </按钮><button onClick={增加}>+ </按钮>

);};

尽管我将处理程序包装到 useCallback 中以避免每次渲染时传递新的处理程序,但仍然必须创建内联箭头函数,但在大多数情况下只能将其丢弃.

如果我只渲染几个组件可能没什么大不了的.但是,如果我这样做 1000 次,对性能的影响有多大?是否有明显的性能损失?有什么办法可以避免它?可能是一个静态处理程序工厂,只有在必须创建新处理程序时才会被调用?

解决方案

React FAQs 对此提供了解释

<块引用>

Hook 是否因为在渲染中创建函数而变慢?

没有.在现代浏览器中,闭包的原始性能与除极端情况外,类没有显着差异.

另外,考虑到 Hooks 的设计在一个几种方式:

Hooks 避免了很多类需要的开销,比如成本在中创建类实例和绑定事件处理程序构造函数.

使用 Hooks 的惯用代码不需要深层组件树嵌套在使用高阶的代码库中很普遍组件、渲染道具和上下文.使用较小的组件树,React 要做的工作更少.

传统上,React 中内联函数的性能问题与如何在每次渲染中断时传递新回调有关子组件中的 shouldComponentUpdate 优化.挂钩从三个方面解决这个问题.

因此钩子提供的整体好处远大于创建新函数的损失

此外,对于功能组件,您可以通过使用useMemo 进行优化,以便组件在其 props 没有变化时重新渲染.

I'm currently very amazed about the use cases of the new react hooks API and what you can possibly do with it.

A question that came up while experimenting was how expensive it is to always create a new handler function just to throw it away when using useCallback.

Considering this example:

const MyCounter = ({initial}) => {
    const [count, setCount] = useState(initial);

    const increase = useCallback(() => setCount(count => count + 1), [setCount]);
    const decrease = useCallback(() => setCount(count => count > 0 ? count - 1 : 0), [setCount]);

    return (
        <div className="counter">
            <p>The count is {count}.</p>
            <button onClick={decrease} disabled={count === 0}> - </button>
            <button onClick={increase}> + </button>
        </div>
    );
};

Although I'm wrapping the handler into a useCallback to avoid passing down a new handler every time it renders the inline arrow function still has to be created only to be thrown away in the majority of times.

Probably not a big deal if I only render a few components. But how big is the impact on performance if I do that 1000s of times? Is there a noticeable performance penalty? And what would be a way to avoid it? Probably a static handler factory that only gets called when a new handler has to be created?

解决方案

The React FAQs provide an explanation to it

Are Hooks slow because of creating functions in render?

No. In modern browsers, the raw performance of closures compared to classes doesn’t differ significantly except in extreme scenarios.

In addition, consider that the design of Hooks is more efficient in a couple ways:

Hooks avoid a lot of the overhead that classes require, like the cost of creating class instances and binding event handlers in the constructor.

Idiomatic code using Hooks doesn’t need the deep component tree nesting that is prevalent in codebases that use higher-order components, render props, and context. With smaller component trees, React has less work to do.

Traditionally, performance concerns around inline functions in React have been related to how passing new callbacks on each render breaks shouldComponentUpdate optimizations in child components. Hooks approach this problem from three sides.

So overall benefits that hooks provide are much greater than the penalty of creating new functions

Moreover for functional components, you can optimize by making use of useMemo so that the components are re-rendering when there is not change in their props.

这篇关于使用 react-hooks 在每次渲染上创建处理程序的性能损失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆