1

I'm trying to call a function while passing the index in. However, I read that it's not best practice to pass a lambda into the onclick handler. Is there a better way of handling this? Because right now isn't a function being created everytime?

Removing the lambda I run the risk of updating the state during a transition which causes infinite calls to the function.

 class MyComponent extends React.Component {
        constructor(props, context) {
            super(props, context);

            this.myFunc= this.myFunc.bind(this);
        }

             myFunc(index){
              //do stuff with the index
             }

            render(){
                const items = this.props.list.map((listItem, index) =>
                     return <div key={listItem.id} onClick={() => this.myFunc(index)}>{listItem.name}</div>
                );

                return(
                    <div>{items}</div>
                )
            }
         }
prawn
  • 2,643
  • 2
  • 33
  • 49

2 Answers2

3

The best way to do it is to extract the list item into a new component:

class ListItem extends React.PureComponent{
   const myFunc = () => {
       const { index } = this.props
       // do something with index
   }  

   render(){
      const { listItem } = this.props
      return (
          <div key={listItem.id} onClick={this.myFunc}>{listItem.name}</div>
      )
   }
}
Alexander Vitanov
  • 4,074
  • 2
  • 19
  • 22
  • Yes this is another good way to achieve it, but this isn't any better in terms of performance. You're replacing a bind with multiple Component instances which is more expensive. – Chase DeAnda Oct 24 '17 at 19:20
  • Depends on the app. As you can see this is a PureComponent and rendering pure component once is way cheaper than creating a function hundreds of times – Alexander Vitanov Oct 24 '17 at 19:47
1

It is recommended in the React Docs to use bind to pass additional params:

myFunc(index, e){
    // Do something with index...
}
render() {
    const items = this.props.list.map((listItem, index) =>
        return <div key={listItem.id} onClick={this.myFunc.bind(this, index)}>{listItem.name}</div>
    );
    return ...
}
Chase DeAnda
  • 15,963
  • 3
  • 30
  • 41
  • Actually .bind is bad for performance too, use https://stackoverflow.com/questions/8656106/why-is-function-prototype-bind-slow for further reference – Alexander Vitanov Oct 24 '17 at 19:08
  • @AlexanderVitanov [it's the recommended way in react](https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers). The performance hit shouldn't be noticeable for most apps. – Chase DeAnda Oct 24 '17 at 19:16
  • the arrow function impact is unnoticeable in most apps too – Alexander Vitanov Oct 24 '17 at 19:48