5 comments

[ 3.5 ms ] story [ 23.0 ms ] thread
In general, the notion of "declaring functions in render is bad for perf" is a result of several things:

- Declaring functions (especially arrow functions) _may_ have had a more noticeable cost in older JS engines

- Misunderstandings about how React's rendering works. When a component renders, React recursively renders all its descendants by default, regardless of whether any of their props have changed or not. New prop references only matters when you are trying to optimize perf by skipping re-renders based on prop reference comparisons (ie, `PureComponent` and `React.memo()`.

- Highly aggressive lint rules, such as the AirBnb ruleset, which include the "no arrow functions in render" rule as a warning or error.

As this post demonstrates, declaring functions isn't zero-cost, but in general the cost is meaningless and it's not something that should be avoided. Micro-benchmarks need to be taken with a grain of salt, but it's nice to have some actual numbers to look at.

Some other prior relevant articles for reference:

- https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-becau...

- https://cdb.reacttraining.com/react-inline-functions-and-per...

> Kitze was kidding (I hope), but for a while this was a very real debate. Especially when render props were first taking off. Since then, Hooks have made anonymous (inline) functions even more popular.

Isn't this missing the point? It's not about the overhead of declaring a new function, it's that you've made one of the props change on every render, so your child element needs to run its render function every time. The render function of Number only has to create a single H1 element which doesn't seem like a good test.

And the ExpensiveComponent example is strange to me. It's being memoized, so what exactly is the point?

> Isn't this missing the point? It's not about the overhead of declaring a new function, it's that you've made one of the props change on every render, so your child element needs to run its render function every time.

This is the larger issue, but the `useCallback` hook can be used to memoize anonymous render functions based on given values to avoid this problem.

Per my comment, by default it doesn't matter whether props change or not. If the parent component renders, its children will too. It's only when you're _trying_ to optimize the child that the new function reference matters.
I see many developers stressing immensely over optimizations that amount to rounding errors.

    if (list[i].type === SomeType && list[i].valid)
Refactored to avoid two array accesses:

    item = list[i]
    if (item.type == SomeType && item.valid)
Then a few months later, somebody refactors the second version to the first version, to avoid an assignment...

I wish people would simply relax and spend that time on more important things.

That said... the performance issue with arrow functions in React isn't related to creating those functions. It has more to do with those functions preventing proper memoization of the components that receive them as props.