Performance penalty of creating handlers on every render with react-hooks

前端 未结 5 2117
野的像风
野的像风 2020-12-03 16:54

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 e

5条回答
  •  温柔的废话
    2020-12-03 17:23

    But how big is the impact on performance if I do that 1000s of times? Is there a noticeable performance penalty?

    It depends on the app. If you're just simply rendering 1000 rows of counters, it's probably ok, as seen by the code snippet below. Note that if you are just modifying the state of an individual , only that counter is re-rendered, the other 999 counters are not affected.

    But I think you're concerned over irrelevant things here. In real world apps, there is unlikely to have 1000 list elements being rendered. If your app has to render 1000 items, there's probably something wrong with the way you designed your app.

    1. You should not be rendering 1000 items in the DOM. That's usually bad from a performance and UX perspective, with or without modern JavaScript frameworks. You could use windowing techniques and only render items that you see on the screen, the other off-screen items can be in memory.

    2. Implement shouldComponentUpdate (or useMemo) so that the other items do not get re-rendered should a top level component have to re-render.

    3. By using functions, you avoid the overhead of classes and some other class-related stuff that goes on under the hood which you don't know of because React does it for you automatically. You lose some performance because of calling some hooks in functions, but you gain some performance elsewhere also.

    4. Lastly, note that you are calling the useXXX hooks and not executing the callback functions you passed into the hooks. I'm sure the React team has done a good job in making hooks invocation lightweight calling hooks shouldn't be too expensive.

    And what would be a way to avoid it?

    I doubt there would be a real world scenario where you will need to create stateful items a thousand times. But if you really have to, it would be better to lift the state up into a parent component and pass in the value and increment/decrement callback as a prop into each item. That way, your individual items don't have to create state modifier callbacks and can simply use the callback prop from its parent. Also, stateless child components make it easier to implement the various well-known perf optimizations.

    Lastly, I would like to reiterate that you should not be worried about this problem because you should be trying to avoid landing yourself into such a situation instead of dealing with it, be leveraging on techniques like windowing and pagination - only loading the data that you need to show on the current page.

    const Counter = ({ initial }) => {
      const [count, setCount] = React.useState(initial);
    
      const increase = React.useCallback(() => setCount(count => count + 1), [setCount]);
      const decrease = React.useCallback(
        () => setCount(count => (count > 0 ? count - 1 : 0)),
        [setCount]
      );
    
      return (
        

    The count is {count}.

    ); }; function App() { const [count, setCount] = React.useState(1000); return (

    Counters: {count}


    {(() => { const items = []; for (let i = 0; i < count; i++) { items.push(); } return items; })()}
    ); } ReactDOM.render(
    , document.querySelector("#app") );
    
    
    
    

提交回复
热议问题