1

I'm using React, and I saw that one common practice is to bind the functions in the constructor, which I also want to use. Though, I don't exactly get how bind works for functions that take parameters. For example, I have something like this:

class MyClass extends Component {
    constructor(props) {
        super(props);

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

    onListClicked(id) {
        // performs some action
    }

    render() {
      return (
        // partially removed for brevity, value of myId comes from a loop
        <ListItem onClick={ () => this.onListClicked(myId) } />
      );
    }
}

Now this works in my case, but I'm not taking advantage of bind fully. If I change the ListItem to <ListItem onClick={this.onListClicked} /> it doesn't work as expected. This would have worked if onListClicked didn't accept any parameters. But, in this case I don't know how to take advantage of bind. Any ideas?

7
  • @ibrahimmahrir it didn't change anything. I don't think the name is the problem here. I need to somehow pass the parameter to the function, in this case the myId. Commented Sep 17, 2017 at 16:42
  • You need to pass the handler to the ListItem component as a prop, and then from there u can call it. Commented Sep 17, 2017 at 16:44
  • And from where myId is coming from? Commented Sep 17, 2017 at 16:45
  • @Prakashsharma inside the render method I have something like: this.state.currentlyDisplayed.map(category => ...) and then myId in my case is something like category.categoryId. So, it comes from using the map function on an array. Commented Sep 17, 2017 at 16:47
  • 1
    @typos In that case the way you are using (i.e. onClick={ () => this.onListClicked(myId) }) is perfectly fine. What problem are you facing? If you want to pass the argument then this way is correct. Commented Sep 17, 2017 at 16:49

2 Answers 2

2

your question has little to do with binding, and is really about how React handles callback props.

Every React event-listener function is passed an instance of React's SyntheticEvent object as its first parameter.

onClick={this.onListClicked} will call the onListClicked function and pass it one parameter: the SyntheticEvent object provided by React.

onClick={this.onListClicked.bind(this)} is the same as the last example. onListClicked.bind() returns a wrapped version of onListClicked with its context object set to this (which in your case is your React component because that's what this is set to when you do the binding). This wrapped version of your function still only receives one parameter: a SyntheticEvent object.

onClick={(e) => this.onListClicked(myId)} will call the anonymous fat-arrow function and pass it one parameter: a SyntheticEvent object, because the anonymous fat-arrow function is the callback and all callbacks get that parameter. This anonymous fat-arrow function ignores its own parameters, and calls this.onListClicked with the value of myId.

onClick={() => this.onListClicked(myId)} is the same as the last example, except we are ignoring the SyntheticEvent because we don't care about it.

onClick={this.onListClicked.bind(this, myId)}, as suggested in another answer, will wrap and call the onListClicked function and pass it TWO parameters: the first is myId (since bind is injecting myId as a parameter as well as setting the context to this) and the second is a SyntheticEvent object.

So: depending on what exactly you are doing inside of onListClicked, you may or may not need to bind it to your React component (or to some other context). Do you actually need variables and functions defined inside a particular object? Then bind your callback context to that object, and call this.foo or this.bar all you need. But if you don't need access to those sorts of things, there's no need to use bind just because it's there.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the clarification.
2

bind function takes a context as its first argument and takes your original function arguments as the next set of arguments after this. The "binded" (excuse me for the horrendous grammar!) function that is returned has the same arguments "binded" to it so when you call it, it will be called with the same set of arguments that it was bound with.

So essentially a <ListItem onClick={ () => this.onListClicked(myId) } /> should be replaced by a <ListItem onClick={this.onListClicked.bind(this, myId)} />

I, however, don't see a way for you to generate the function you need in the constructor itself since you won't have those arguments there to start with. You could loop over the array in the constructor itself and create those "binded" functions there only but that would be just a waste and a much elegant solution would be to use the above said method.

Read more about bind from MDN.


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.