Inside my render return() I have these:
<button onClick={ this.selectTimeframe('Today') }
className={ this.setActiveIf('Today') } type="button">Today</button>
Which is this function:
selectTimeframe(timeframe) {
// this.setState({ timeframe });
}
^ I have to comment out the setState for now otherwise I'll get that error I posted above and the app breaks.
I have this in my constructor:
this.selectTimeframe = this.selectTimeframe.bind(this);
I found this answer here, but it does not make sense, how am I suppose to pass in variable? Or is he saying that every unique button needs a unique function? As to avoid calling it inside of the render?
import React from 'react';
export class TimeframeFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
timeframe: 'Today'
};
this.selectTimeframe = this.selectTimeframe.bind(this);
this.setActiveIf = this.setActiveIf.bind(this);
}
componentDidMount() {
console.log('%c TimeframeFilter componentDidMount', 'background: #393939; color: #bada55', this.state);
}
selectTimeframe(timeframe) {
// this.setState({ timeframe });
}
setActiveIf(timeframe) {
return this.state.timeframe === timeframe ? 'btn btn-default active' : 'btn btn-default';
}
render() {
return (
<div className="fl">
<span className="label label-default mr10">Timeframe</span>
<div className="btn-group btn-group-sm mr20" role="group">
<button onClick={ this.selectTimeframe('Today') }
className={ this.setActiveIf('Today') } type="button">Today</button>
<button onClick={ this.selectTimeframe('Week') }
className={ this.setActiveIf('Week') } type="button">Week</button>
<button onClick={ this.selectTimeframe('Month') }
className={ this.setActiveIf('Month') } type="button">Month</button>
<button onClick={ this.selectTimeframe('Year') }
className={ this.setActiveIf('Year') } type="button">Year</button>
<button onClick={ this.selectTimeframe('All') }
className={ this.setActiveIf('All') } type="button">All</button>
</div>
</div>
);
}
}
export default TimeframeFilter;
State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.
To update our state, we use this. setState() and pass in an object. This object will get merged with the current state.
Whenever we update the state using the setState() method it re-renders the current component and its child components. When we call the setState function it receives the latest state snapshot. Then we can use it inside the setState() function and return the new value to which we want to update the new state value to.
You may call setState() immediately in componentDidMount() . It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won't see the intermediate state.
You should be passing the value to the onClick
function using arrow function or bind method
otherwise it just executes to return value to onClick
everytime rerender occurs and if you use setState
in it, it will call a rerender
and the funciton to call again and thus repeating the process.
Do it like
<button onClick={ ()=> this.selectTimeframe('Today') }
className={ this.setActiveIf('Today') } type="button">Today</button>
or
<button onClick={ this.selectTimeframe.bind(this, 'Today') }
className={ this.setActiveIf('Today') } type="button">Today</button>
Hope I was able to explain it to you clearly. :)
EDIT: Although the above approach solves the problem but isn't the optimal approach due to the performance reasons. We should avoid method binding inside render because during re-rendering it will create the new methods instead of using the old one, that will affect the performance.
See this answer on How to avoid binding inside the render method
Currently you call this.selectTimeframe('Today')
in your render method.
You probably want to
onClick={() => this.selectTimeframe('Today') }
or a bit smarter way
<button onClick={ this.selectTimeframe.bind(this, 'Today') } className={ this.setActiveIf('Today') } type="button">Today</button>
selectTimeframe.bind(key) {
switch(key){
case 'Today':
//your logic
break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With