8

Im novice to React js, i don't know whats wrong with below code, but i'm getting setState is not a function error.Please help me to fix this.

class AppBarLayout extends React.Component {
  constructor(props) {
      super(props);

      this.state = {
        visibleSideBar:true,
        slide:""
      }
  }
  showProfile(){

    this.setState({
        slide:'slide'
    });
    console.log(this.state.slide);
  }
  render(){
    return(
            <div>
        <header>
          <NavBar show={this.showProfile}/>
          <Profile slide={this.state.slide} />
        </header>
      </div>
    );
  }
}
export default AppBarLayout;
veeran
  • 352
  • 1
  • 6
  • 16
  • Possible duplicate of [Unable to access React instance (this) inside event handler](http://stackoverflow.com/questions/29577977/unable-to-access-react-instance-this-inside-event-handler) – Felix Kling Feb 19 '17 at 18:44

4 Answers4

18

You need to bind this.showProfile in the component constructor

this.showProfile = this.showProfile.bind(this)

More detail about this on the Handling Events page of the React doc : https://facebook.github.io/react/docs/handling-events.html

Delapouite
  • 9,469
  • 5
  • 36
  • 41
11

Expanding on Delapouite's answer if you don't like to bind every function in the constructor you can use arrow functions to automatically bind to the correct context.

For example:

class AppBarLayout extends React.Component {
  constructor(props) {
      super(props);

      this.state = {
        visibleSideBar:true,
        slide:""
      }
  }

  // Now showProfile is an arrow function
  showProfile = () => {
    this.setState({
        slide:'slide'
    });
    console.log(this.state.slide);
  }

  render(){
    return(
      <div>
        <header>
          <NavBar show={this.showProfile}/>
          <Profile slide={this.state.slide}/>
        </header>
      </div>
    );
  }
}
export default AppBarLayout;
Community
  • 1
  • 1
César Alberca
  • 2,321
  • 2
  • 20
  • 32
  • Be careful using this syntax, it is not standard (yet) and needs a specific Babel transformation. – Delapouite Feb 19 '17 at 12:45
  • Yup, although it's getting [quite there](http://caniuse.com/#search=arrow%20functions) – César Alberca Feb 19 '17 at 13:12
  • I know this is a few years old now, but has this become standard now? I'm new to React and want to learn the best practices. I like how this is more terse and flexible so I hope it is the standard. –  Jan 20 '20 at 19:16
  • It's most likely that it will land in JavaScript, as it is in stage 3: https://github.com/tc39/proposal-class-fields – César Alberca Jan 20 '20 at 20:21
4

In my case, I solved the problem without binding.

Declaring the method like this was generating the error:

  async onSubmit(e) {
     event.preventDefault();
     this.setState({ shopEthereumAddress: e.target.id });
  }

The CORRECT declaration which will not generate the error is this:

onSubmit = async event => {
    event.preventDefault();
    this.setState({ shopEthereumAddress: event.target.id });
}

This works.

Riccardo Persiani
  • 702
  • 1
  • 5
  • 25
3
toggleSwitch() {
    this.setState({
        name: 'Ram ji'
    });
} 

Using an arrow function keeps the context of this set to the parent scope. The main benifit of arrow functions apart from being more concise is

Main benefit: No binding of ‘this’

// use this arrow function instead of
toggleSwitch = () => {
    this.setState({
        name: 'Ram ji'         //It's working
    });
}
Lex
  • 4,749
  • 3
  • 45
  • 66
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53