Manage-state-locally-first

Tell us what’s happening:
Hello @here, I’m finding it difficult to pass the last test in this challenge, React and redux: Manage state locally first the code below is what I’ve been able to come up with, but I don’t seem to get how to use the <ul> that’s required in the challenge and to pass the last test.

I would really appreciate help with this. Thanks

Your code so far


class DisplayMessages extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      messages: []
    }
    this.handleChange = this.handleChange.bind(this)
    this.submitMessage = this.submitMessage.bind(this)
  }
  // add handleChange() and submitMessage() methods here
  handleChange(event) {
    this.setState({
      input: event.target.value
    })
  }
  
  submitMessage() {
    this.state.messages.concat(this.state.input)
   this.setState({
     input: ''
   })
  }

  render() {
    return (
      <div>
        <h2>Type in a new Message:</h2>
        { /* render an input, button, and ul here */ }
      <input onChange={this.handleChange} value={this.state.input}/>
        <button onClick={this.submitMessage}>submit</button>
        <ul></ul>
        { /* change code above this line */ }
      </div>
    );
  }
};

Your browser information:

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

Link to the challenge:

1 Like

The issue is here:

  submitMessage() {
    this.state.messages.concat(this.state.input)
    this.setState({
      input: ''
    })
  }

The first line - you would never change state directly. Typically, I would create a dummy variable and change it there, with a copy of the data. Remember that arrays cannot be simply copied. You will need to use slice or the spread operator. So, in ES5,:

let arr = [1, 2]
let arrCopy = arr.slice()
arrCopy.push(3)

In ES6, you can do:

let arr = [1, 2]
let arrCopy = [...arr, 3]

Often I create a variable like newMessages.

Then the other issue is that you need to change the state in your setState function. You’re already doing it for the input, you just need to also do it for the messages.

Let us know if this is still confusing.

3 Likes

Thanks for helping out @kevinSmith, I refactored the submitMessage method to use ES6 and also set the state of the messages as you suggested but still can’t pass the last test:

Here’s the code I have for the submitMessage method now:

submitMessage() {
   [...this.state.messages, this.state.input]
   this.setState({
     messages: [],
     input: ''
   })
  }

Can I see your code implementation for passing all the tests? Would really appreciate that.

You’re almost there. You just have to fix a few things.

[...this.state.messages, this.state.input]

Great. That makes a copy of this.state.messages without changing the original and adds this.state.input to. Perfect. But where is that being saved? You need to save it in a variable:

let newMessages = [...this.state.messages, this.state.input]

Then, you need to put that into state:

   this.setState({
     messages: newMessages,
     input: ''
   })

Does that make sense? Just those two changes and it should work.

Alternatively, you could do it all in one step, without a variable, but this is a very common pattern that you’re going to see so it pays to get used to it.

Can I see your code implementation for passing all the tests? Would really appreciate that.

Like I said, you’re almost there and you’ll learn better if you do it yourself. But let me know if this doesn’t do it and I’ll try to do a better job explaining.

2 Likes

You’re the man @kevinSmith. I’m really grateful for your help every step of the way. Storing the message in a variable as you suggested worked for me and I was able to pass all the tests.

Something else i noticed was that I didn’t get to use the <ul> that was stated in the question, but anyways, I passed all the tests now and I’m very happy and grateful. Thanks a lot man!

1 Like

That’s a good point. I guess that is a bug. That’s why it is beta. In order to pass the test, you should have had to do something like:

        <ul>
          {this.state.messages.map(msg => <li>{msg}</li>)}
        </ul>

I’ll look into it when I get back from my run.

3 Likes

I’m also having problems with this challenge :frowning_face:

My code looks like this:

class DisplayMessages extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      messages: []
    };
    
    this.handleChange = this.handleChange.bind(this);
    this.submitMessage = this.submitMessage.bind(this);
  }
  
  handleChange(event) {
    this.setState({
      input: event.target.value
    });
  }

  
  submitMessage() {
    let newMessages = [...this.state.messages, this.state.input]
    this.setState({
      messages: newMessages,
      input: ''
    });
  }
  
  render() {
    return (
      <div>
        <h2>Type in a new Message:</h2>
        <input value={this.state.input} onchange={this.handleChange}/><br/>
        <button onClick={this.submitMessage}>Submit</button>
        <ul>
          {this.state.messages.map(msg => <li>{msg}</li>)}
        </ul>
      </div>
    );
  }
};

This code passes the two first tests, the rest fails…
Any help will be appreciated! Thnx

1 Like

You have a typo on this line:

<input value={this.state.input} onchange={this.handleChange}/><br/>

I’ll let you find it. If you need a hint - “camel case”.

2 Likes

:roll_eyes: onChange…Thanx!!

2 Likes

This was great. Please update this.

Thank for this solution

Is there a reason why onSubmit does not work for this challenge? For example, the button tag:

<button onSubmit={this.submitMessages} type="submit">Add message</button>

Now that I’m typing this out, onSubmit would have to be on a form tag for it to work, correct?

Kind of answered it on my own, onSubmit DOES work IF it is on the form tag AND submitMessage has event.preventDefault() in it’s formula. So…

submitMessage(){
event.preventDefault();
.......}

<form onSubmit={this.submitMessage}>
<input onChange={this.changeMessage} />
<button type="submit">Add Message </button>
</form>

Only problem with that is, for some reason despite the submitMessage functions being exactly the same between onSubmit and onClick, input does not clear with onSubmit. Input does clear with onClick.

Should the submitMessage() have event.preventDefault() if it ‘event’ happens to be called as a param to prevent default behaviour that is hard page reload or is just fine without the event object as a parameter?