by Cory House
React Pattern: Extract Child Components to Avoid Binding
Here’s a common scenario in React: You’re mapping over an array, and you need each item to call a click handler and pass some relevant data.
Here’s an example. I’m iterating over a list of users and passing the userId to delete to the deleteUser function on line 31.
Here’s a working example on Codesandbox. (which is awesome 😍)
So What’s the Problem?
I’m using an arrow function in the click handler. This means every time render runs, a new function is allocated. In many cases, this isn’t a big deal. But if you have child components, they’ll re-render even when data hasn’t changed because each render allocates a new function.
Bottom line: Avoid declaring arrow functions or binding in render for optimal performance. My team uses this ESLint rule to help alert us to this issue.
What’s the Solution?
So how do you avoid binding and arrow functions in render? One option is to extract a child component. Here, I’ve extracted the list item to UserListItem.js:
Then, the parent component’s render gets simpler, and no longer needs to contain an arrow function. It passes the relevant context for each list item down via props in the new “renderUserListItem” function.
Note that instead of using an arrow function in render while mapping, we’re calling a new function declared outside of render on line 19. No more function allocations on each render. 👍
Here’s a working example of this final refactor.
Yay or Yuck?
This pattern improves performance by eliminating redundant function allocations. So it’s most useful when this situation applies to your component:
- Render is called frequently.
- Rendering children is expensive.
Admittedly, extracting a child component as I’ve suggested above is extra work too. It requires more moving parts, and more code. So if you’re not having performance issues, it’s arguably a premature optimization 🙈.
So you have two options: Either allow arrows and binds everywhere (and deal with perf issues if they pop up), or forbid them for optimal performance and consistency.
Bottom-line: I recommend disallowing arrows and binds in render. Here’s why:
- You have to disable the useful ESLint rule I suggested above to allow it.
- Once you disable a linting rule, people are likely to copy this pattern and start disabling other linting rules. An exception in one place can quickly become the norm…
So I find extracting child components a useful pattern to avoid binding in render.
Have another way you like to handle this? Chime in via the comments!
Looking for More on React? ⚛