Performance Testing React with Anonymous Functions
matthewgerstman.com
matthewgerstman.com
- 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...
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.
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?
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.