FAQ: this.state - Call this.setState from Another Function

This community-built FAQ covers the “Call this.setState from Another Function” exercise from the lesson “this.state”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development

Learn ReactJS: Part I

FAQs on the exercise Call this.setState from Another Function

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

When you are accessing the function using dot notation, you omitted the parenthesis, like this:

 this.toggleMood = this.toggleMood.bind(this);

Why is this and how does that work?

The .bind() method creates a new function, so the right hand side is also a function. Thus, that line redefines this.toggleMood as another function created by the .bind() method. The reason for doing this is explained in the exercise description:

Due to the way that event handlers are bound in JavaScript, this.toggleMood() loses its this when it is used on line 20. Therefore, the expressions this.state.mood and this.setState on lines 7 and 8 won’t mean what they’re supposed to… unless you have already bound the correct this to this.toggleMood .

That is why we must bind this.toggleMood to this on line 8.

For an in-depth explanation of this kind of binding trickery, begin with the React docs. For the less curious, just know that in React, whenever you define an event handler that uses this , you need to add this.methodName = this.methodName.bind(this) to your constructor function.

(I think “lines 7 and 8” in this text is a mistake for “lines 12 and 13”. I reported it as a bug the other day, but it has not been fixed for now.) More detailed explanations will be found in the React docs linked in this text and the document about the .bind() method.

1 Like

I tried using this.setState() inside render() method.It seems to be working fine.Why?

import React from 'react';

import ReactDOM from 'react-dom'

const green = '#39D1B4';

const yellow = '#FFD712';

class Toggle extends React.Component {

  constructor(props){

    super(props);

    this.state={color:green};

   // this.changeColor=this.changeColor.bind(this);

  }

  // changeColor(){

  //   this.setState(this.state.color==green?{color:yellow}:{color:green});

  // }

  render() {

    return (

      <div style={{background:this.state.color}}>

        <h1>

          Change my color

        </h1>

       <button onClick={()=>this.setState(this.state.color==green?{color:yellow}:{color:green})}>

  Change color

</button>

      </div>

    );

  }

}

ReactDOM.render(<Toggle/>,document.getElementById('app'));

HI, Can anyone tell me why my button won’t change the color?

import React from ‘react’;
import ReactDOM from ‘react-dom’;

const green = ‘#39D1B4’;
const yellow = ‘#FFD712’;

class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { color: green };
}
changeColor() {
const changeColor = this.state.color == green ? green : yellow;
this.setState({ color: changeColor });
this.changeColor = this.changeColor.bind(this);
}
render() {
return (
<div style={{background: this.state.color}}>


Change my color



Change color


);
}
}

ReactDOM.render(
,
document.getElementById(‘app’)
);

const changeColor = this.state.color == green ? yellow : green;
and
this.changeColor = this.changeColor.bind(this); put this in constructor
This will work

2 Likes

import React from ‘react’;

import ReactDOM from ‘react-dom’;

const green = ‘#39D1B4’;

const yellow = ‘#FFD712’;

class Toggle extends React.Component {

constructor(props){

super(props);

this.state={

  color: green

}

this.changeColor=this.changeColor.bind(this);

}

changeColor(){

const newColor = (this.state.color == yellow) ? green : yellow;

this.setState({color: newColor});

}

render() {

return (

  <div style={{background: this.state.color}}>

    <h1>

      Change my color

    </h1>

    <button onClick={this.changeColor}>

      Change color

    </button>

  </div>

);

}

}

ReactDOM.render(, document.getElementById(‘app’));

An alternative solution for using this in your method:
you can convert your method to an arrow function, with that you will not have to use bind.

ex:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { weather: 'sunny' };
  }
 
  makeSomeFog = () => {
    // will work without bind because we are using an arrow function    
    this.setState({ 
      weather: 'foggy'
    });
  }
}
1 Like

you haven’t used “setState” in your render method, you are using “setState” on an event handler which will only execute when you click the button.

but you can’t use “setState” directly in your render methods, why?

changing your state is causing your component to re-render so imagine you are using setState directly in your render method, it’s an infinite loop!! changing the state will make a re-render and render will cause a setState which will change the state and causing a re-render again and again.

2 Likes

Hello!!
I’d have a question regarding this exercise…
Why does this.changeColor = this.changeColor.bind(this);
must be placed under the constructor method, and not under the changeColor method?

I use this opportunity to tip my hat to the creators of this react course. Really well made, and much funnier than the other classes that I took in codacademy :slight_smile:

Best,

The code in that line redefines this.changeColor as another function. If you know what this is doing, you’ll probably know why this line is in the constructor. I’ve posted earlier about what this kind of line is doing, so I hope you find it helpful.

Hello everyone,

I’m not sure to understand why <div style={{background: this.state.color}}> should be written with two curly braces, is someone could please explain it to me?

Thanks a lot!

In JSX, JavaScript expressions are written inside curly braces, and since JavaScript objects also use curly braces, the styling is written inside two sets of curly braces {{}}

From below resourse
https://www.w3schools.com/react/react_css.asp

1 Like

Hi aravin77,

Thanks for your answer, makes sense!

Why can I set state with an equals operator this.state = {...} in the constructor? Aren’t you supposed to use this.setState({...}) to write to state?

Re: Call this.setState from Another Function at:

https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-22-react-part-ii/modules/wdcp-22-components-interacting/lessons/this-state/exercises/call-setstate-another-function

This is first example in the linked React documentation of avoiding having to manually bind the handler function.

The code does not work in CodePen. The handleClick method does not get called when clicking on the button.
Can someone see what is wrong? This was copied and pasted directly from the React document. I only added the
two lines.

//html
<div id="root"></div>

//css
body {
    padding: 5px
}

//code
class LoggingButton extends React.Component {

  // This syntax ensures `this` is bound within handleClick. me: (this is a React doc comment)
  handleClick = () => {
    console.log('this is:', this);
  };
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<LoggingButton />);

I still don’t understand the whole bind thing.

Due to the way that event handlers are bound in JavaScript, this.toggleMood() loses its this

How can an event handler ‘lose it’s this’. What does that mean?

I just realised that we are learning class components and not functional components. I think it would have been better if you could make a note about it. Otherwise, I think its a bit confusing to differentiate between two.