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.

import React from 'react';

class App extends React.Component {
  constructor() {
    this.state = {
      users: [
        { id: 1, name: 'Cory' }, 
        { id: 2, name: 'Meg' }
      ]
    };
  }
  
  deleteUser = id => {
    this.setState(prevState => {
      return { users: prevState.users.filter( user => user.id !== id)}
    })
  }

  render() {
    return (
      <div>
        <h1>Users</h1>
        <ul>
        { 
          this.state.users.map( user => {
            return (
              <li key={user.id}>
                <input 
                  type="button" 
                  value="Delete" 
                  onClick={() => this.deleteUser(user.id)} 
                /> 
                {user.name}
              </li>
            )
          })
        }
        </ul>
      </div>
    );
  }
}

export default App;

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:

import React from 'react';
import PropTypes from 'prop-types';

class UserListItem extends React.Component {
  onDeleteClick = () => {
    // No bind needed since we can compose 
    // the relevant data for this item here
    this.props.onClick(this.props.user.id);
  }

  // No arrow func in render! ?
  render() {
    return (
      <li>
        <input 
          type="button" 
          value="Delete" 
          onClick={this.onDeleteClick} 
        /> 
        {this.props.user.name}
      </li>
    );
  }
}

UserListItem.propTypes = {
  user: PropTypes.object.isRequired,
  onClick: PropTypes.func.isRequired
};

export default UserListItem;

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.

import React from 'react';
import { render } from 'react-dom';
import UserListItem from './UserListItem';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [{ id: 1, name: 'Cory' }, { id: 2, name: 'Sherry' }],
    };
  }

  deleteUser = id => {
    this.setState(prevState => {
      return { users: prevState.users.filter(user => user.id !== id) };
    });
  };

  renderUserListItem = user =>
    <UserListItem key={user.id} user={user} onClick={this.deleteUser} />;

  render() {
    return (
      <div>
        <h1>Users</h1>
        <ul>
          {this.state.users.map(this.renderUserListItem)}
        </ul>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

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:

  1. Render is called frequently.
  2. 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:

  1. You have to disable the useful ESLint rule I suggested above to allow it.
  2. 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? ⚛

I’ve authored multiple React and JavaScript courses on Pluralsight (free trial). My latest, “Creating Reusable React Components” just published! ?

1*BkPc3o2d2bz0YEO7z5C2JQ

Cory House is the author of multiple courses on JavaScript, React, clean code, .NET, and more on Pluralsight. He is principal consultant at reactjsconsulting.com, a Software Architect at VinSolutions, a Microsoft MVP, and trains software developers internationally on software practices like front-end development and clean coding. Cory tweets about JavaScript and front-end development on Twitter as @housecor.