5

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?

Full code

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;
Community
  • 1
  • 1
Leon Gaban
  • 36,509
  • 115
  • 332
  • 529

2 Answers2

3

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

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
1

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;
  }
}
kurumkan
  • 2,635
  • 3
  • 31
  • 55