Reputation: 6642
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
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
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