Reputation: 753
I am learning React. In a test app I'm writing, I am rendering some buttons with onClick methods. When they are rendered like this, they work and call the selectMode function as expected when clicked.
constructor(props) {
super(props);
this.state = { mode: 'commits', commits: [], forks: [], pulls: [] };
}
...
selectMode(mode) {
this.setState({ mode });
}
render() {
...
return (<div>
<button onClick={this.selectMode.bind(this, 'commits')}>Show Commits</button><br/>
<button onClick={this.selectMode.bind(this, 'forks')}>Show Forks</button><br/>
<button onClick={this.selectMode.bind(this, 'pulls')}>Show Pulls</button>
</div>
)
}
But when I tried the suggested best practices way shown below, by binding in the constructor, the selectMode function is called three times when the component is rendered. Why are the onClick event handlers being called then? What do I have wrong?
constructor(props) {
super(props);
this.state = { mode: 'commits', commits: [], forks: [], pulls: [] };
this.selectMode = this.selectMode.bind(this)
}
...
selectMode(mode) {
this.setState({ mode });
}
render() {
...
return (<div>
<button onClick={this.selectMode('commits')}>Show Commits</button><br/>
<button onClick={this.selectMode('forks')}>Show Forks</button><br/>
<button onClick={this.selectMode('pulls')}>Show Pulls</button>
</div>
)
}
Upvotes: 1
Views: 1313
Reputation: 3056
your this.selectMode(...)
is executed IMMEDIATELY whenever your component is rendered.
<.. onClick={this.selectMode('commits')}..../> <-- function is called immediately
You can use arrow function
to create an anonymous function in which you can call your method. In this way, you this.selectMode
method only get called when the click event occurs :
<.. onClick={() => this.selectMode('commits')}..../>
If you don't want to create anonymous functions everytime you render the component, you can store an value to an attribute of the element. Like this :
constructor(props) {
super(props);
this.state = { mode: 'commits', commits: [], forks: [], pulls: [] };
this.selectMode = this.selectMode.bind(this)
}
selectMode(event){
this.setState({mode: e.target.name});
}
render(){
....
<.. onClick={this.selectMode} name='commits' ..../>
..}
Upvotes: 5
Reputation: 1377
I'm not sure, but I think it's because you call upon each onClick function by adding the parentheses. If you use ES6 you could try doing this:
onClick = () => { this.selectMode('commits') }
onClick = () => { this.selectMode('forks') }
onClick = () => { this.selectMode('pulls') }
Upvotes: 1