Set state code block

There is something off about toggleVisibility. It is hard to understand what is happening in its setState function.

class MyComponent extends React.Component {
constructor(props) {
  super(props);
  this.state = {
    visibility: false
  };
  // Change code below this line
  this.toggleVisibility = this.toggleVisibility.bind(this);
  // Change code above this line
}
// Change code below this line
  toggleVisibility = (state, prop) => setState(
{this.state.visibility ? false : true}
);
// Change code above this line
render() {
  if (this.state.visibility) {
    return (
      <div>
        <button onClick={this.toggleVisibility}>Click Me</button>
        <h1>Now you see me!</h1>
      </div>
    );
  } else {
    return (
      <div>
        <button onClick={this.toggleVisibility}>Click Me</button>
      </div>
    );
  }
}
}
  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.50.

Challenge: Use State to Toggle an Element

Link to the challenge:

Set state is one callback function, toggleVisibility is another. (state, prop) belong to set state examples. For this case prop is not needed as we are using a state, not a prop.
You are trying to make this a function. It is incomplete.

Why is set state inside of toggleVisibility? Set state is usually on its own. With this keyword, state is already connected to toggleVisibility


  toggleVisibility () {
    this.setState(state => 
  ({visibility: !state.visibility}));
  }
//Set state not inside a function
 this.setState(state => 
  ({visibility: !state.visibility}));

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.50.

Challenge: Use State to Toggle an Element

Link to the challenge:

I don’t understand what you mean that setState is usually “on its own”. Do you mean not in a function? I would say that it is always in a function. It is always going to be called in a class method. Maybe some of the training materials separated it out for simplification purposes, but irl, I can’t think of a case where setState wouldn’t be called in a class method. Perhaps you could pass it to a helper function, but it would still be called there, inside a function.

Can you clarify what you mean?

Hi @crystalio303 !

I have merged your two posts together since they deal with the same challenge.

1 Like

Set state is one callback function, toggleVisibility is another.

I wouldn’t call those callback functions but just functions. A callback is usually a function that you pass into some other function.

(state, prop) belong to set state examples.

I don’t understand.

For this case prop is not needed as we are using a state, not a prop.

True.

You are trying to make this a function. It is incomplete.

I don’t understand.

This is what you have:

  toggleVisibility = (state, prop) => setState({this.state.visibility ? false : true});

Yes, this part (state, prop) doesn’t need to be there - that can just be () because not only do we not need these passed in, we normally wouldn’t. This is a class method so it can access state and props off of this.

Your other problem is that you need to pass setState a valid object. (There is also a way to pass it a callback function, but let’s not worry about that right now.

So, you need to pass an object. This

{this.state.visibility ? false : true}

because it has no property name. I would expect to see the prop named “visibility” there.

And if we’re going to do that, I’d rather simplify the logic.

  toggleVisibility = () => setState({this.state.visibility ? false : true});

Also, the expression:

this.state.visibility ? false : true

could be simplified to:

!this.state.visibility

Checking set state, it always is inside a function. That confusion is cleared.
Right, that was mistyped. Restated, Set state is one callback function and toggleVisibility is another function.
(state, prop) was used as the argument for the example. That is not the argument the code will necessarily be.
How set state was, was not a working function. In that way it was incomplete.
Thanks for this line. It shows that state and prop are passed to toggleVisibility.

This is another update of toggleVisibility with those props.

  toggleVisibility = (state, prop) => setState({this.state.visibility ? false : true});

One of the requirements is to pass an updater function to setState. Also, it should be this.setState().

An anonymous function should be passed to setState.

this should not be used inside setState

Would you mind posting your current code?


Edit: I would suggest you declare toggleVisibility as a normal method with no parameters. It isn’t the handler method that receives the state and props, it is the updater callback function inside setState.

Call this.setState inside the handler method, pass setState the currect state this.setState(state => state.someStateValue). Return an object inside the call to setState with the correct property set to the return value of your ternary (or use the ! operator as suggested instead).

Set state is one callback function and toggleVisibility is another function.

Again, I wouldn’t call either of those a callback. Callbacks will be functions passed as parameters to other functions. They are passed in so that they can be “called back” later. They are often used for asynchronous operations or as a function to define how something is to be done, as is common with the object and array prototype methods.

And again:

 toggleVisibility = (state, prop) => setState({this.state.visibility ? false : true});

This isn’t valid JavaScript. Again, that object needs a property name. For example:

 setValue = () => setState({ value: 0 });

or

 incrementValue = () => setState({ value: this.state.value + 1 });

In this case, the property name is “value”.

And as noted, you do not need (state, props) as a parameter list as 1) Those parameters are not used, and 2) They are not being passed in anyway and we don’t need to since they are class properties and are already accessible.

Set state receives the parameters of the method.
Set state is not a callback.

function print(callback) {  
    callback();
}

Yes, the ternary is not valid.
The solution

class MyComponent extends React.Component {

  constructor(props) {

    super(props);

    this.state = {

      visibility: false

    };

    // Change code below this line

    this.toggleVisibility = this.toggleVisibility.bind(this);

    // Change code above this line

  }

  // Change code below this line

    toggleVisibility () {

      this.setState(state => 

    ({visibility: !state.visibility}));

    }

  // Change code above this line

  render() {

    if (this.state.visibility) {

      return (

        <div>

          <button onClick={this.toggleVisibility}>Click Me</button>

          <h1>Now you see me!</h1>

        </div>

      );

    } else {

      return (

        <div>

          <button onClick={this.toggleVisibility}>Click Me</button>

        </div>

      );

    }

  }

}

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

Yes, that will work. That is a good implementation.

Note that you’ve switched from the object form to the function form of setState. Both will work - I think this is better since the new state depends on the old state.

You could have fixed what you had before with:

    toggleVisibility = () => this.setState({visibility: !this.state.visibility});

But either work and what you have know is better.

It was difficult to find the words to correct the ternary and it was a leap to fill the value as what you have done. !this.state.visibility is the result of the state being false.

visibility: !this.state.visibility

Well, the ternary could work, you just needed a property:

{ visibility: this.state.visibility ? false : true }

That does the same thing as:

{ visibility: !this.state.visibility }

But I think the second is cleaner and clearer.