typos
typos

Reputation: 6642

How to use bind in React?

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?

Upvotes: 1

Views: 162

Answers (2)

Dan O
Dan O

Reputation: 6090

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.

Upvotes: 2

Mustansir Zia
Mustansir Zia

Reputation: 1004

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.


Upvotes: 2

Related Questions