4

If declaring an arrow function inside a react class component is bad for performance, why does declaring variables(arrow functions) inside a functional component have better performance?

The way React is now moving towards using the entire app with only functional components, won't it have performance issues for big apps that have long component trees with lots of variables that being redeclared on each update? (I know some are garbage collected but the declaration still occurs, same as using arrow function inside the render function of a class component)

class ReactComponent extends React.Component {
    render() {
        return (
            <div onClick={() => console.log('do something')}>
                <SomeOtherComponent onChange={() => console.log('pass function')} />
            </div>
        );
    }
}

const functionalComponent = () => {
    const doSomething = () => console.log('do something');
    const passFunction = () => console.log('pass function');
    return (
        <div onClick={doSomething}>
            <SomeOtherComponent onChange={passFunction} />
        </div>
    );
};
2
  • Please provide a code sample, so we can discuss based on the code provided. Commented May 10, 2020 at 17:39
  • 1
    @LazaroFernandesLimaSuleiman I've added an example Commented May 11, 2020 at 7:34

2 Answers 2

4

Nothing is "bad for performance", there are only unnecessary computations. If creating a function is necessary to express the behaviour of a program, there is nothing "bad". It is only "bad" if creating the function can be avoided, and it is even worse if a lot of computations can be avoided.

Creating a function is cheap. It creates a new function object, that contains a reference to the functions code as well as to it's environment (the "closure"), so a function expression is not much different than an object literal. Therefore creating functions is not "bad", and it never was.

The real problem that arises from function expressions in React, is not the function expression itself, but the logical result of it:

<div onClick={() => doStuff()}> Test </div>

On every rerender, a new function object gets created, that references a different environment, that might contain a different doStuff method, that might do something different. Therefore on every rerender, React has to detach the listener, and attach a new one referencing the new function, so that the new behaviour gets triggered. For one listener this is cheap, but if you pass down functions to other components, that pass down functions to other components, the cost multiplies (= more components have to rerender), so it might get expensive (= something we might worry about). If the function changes, but what it does does not, reattaching the listeners is uneccessary, and thus it can be avoided by making sure that functions only get recreated when the values they depend on get recreated:

 const callback = useCallback(() => doStuff(), [doStuff]); // returns the same function, unless doStuff changes

 <div onClick={callback}> Test </div> <- only gets reattached when doStuff changes
Sign up to request clarification or add additional context in comments.

Comments

1

If declaring an arrow function inside a react class component is bad for performance

The reason people warn you about creating functions on every render is not because creating functions is slow. It's not; creating functions is very fast.

The performance issue comes when you pass that function to something else, and that something else is using shouldComponentUpdate or PureComponent or React.memo or useMemo or some other form of memoization. Since it received a new function, it thinks it needs to recompute, and so the memoization benefit is lost.

It's true that this issue can occur in function components too, but that's one of the things that useCallback and useMemo are for. You can use those hooks to create the function only once, and thus you will not needlessly break memoization of other components.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.