anhtv13
anhtv13

Reputation: 1818

React setState for an object incorrect

I'm new to React and I want to update the state of an object when the input changes its value.

I've searched some references relating to this and there are several solutions, like this. However, it doesn't work correctly for me.

Applied this solution, I get the value incorrectly. For example, I type the input value: "name", but the value I get is only "nam". The last character is missing.

What's wrong here? Anyone here can help me? Thank you in advanced.

Here is my code for component AddHero.js

import React, { Component } from 'react';

class AddHero extends Component {

constructor(props) {
    super(props);

    this.state = {
        hero: {}
    };

    this.addHero = this.addHero.bind(this);
    this.nameChange = this.nameChange.bind(this);      
}

addHero() {

}

nameChange(event) {
    var temp = {...this.state.hero};
    temp.Name = event.target.value;   
    this.setState({hero:temp});

    console.log(this.state.hero.Name);//the value of Name is always missing the last character from the input
}   

render() {
    return (
        <div>
            <div className="name">
                <label>Name: </label>
                <input type="text" id="Name" onChange={this.nameChange} />
                {/* <p class="alert alert-danger invalid" >Invalid Name</p> */}
            </div>

            <div className="submit">
                <button type="button" onClick={this.addHero} >Add new</button>
            </div>
        </div>
    );
}
}

export default AddHero;

Here is the snapshot:

enter image description here

Upvotes: 1

Views: 1470

Answers (4)

BrunoLM
BrunoLM

Reputation: 100381

Whenever you need to update the state based on a previous state you have to use the updater argument

If you need to set the state based on the previous state, read about the updater argument below. https://reactjs.org/docs/react-component.html#setstate

Basically it is calling setState with a callback function

this.setState((state) => ({ hero: { ...state.hero, Name: 'foo' } }))

Upvotes: 1

Dacre Denny
Dacre Denny

Reputation: 30390

The setState method doesn't change the state of the component immediatly. One solution to your problem however, is to make use of the setState() method's callback (which gets called when the state change has taken effect).

Consider the following which shows how you can log the state of your component, after the state change has taken effect:

nameChange(event) {
    var temp = {...this.state.hero};
    temp.Name = event.target.value;   

    this.setState({hero:temp}, 
    () => { // Callback called when state change has been applied

       // Prints the latest state for hero.name
       console.log(this.state.hero.Name);
    });
}  

Upvotes: 2

Orgil
Orgil

Reputation: 251

Likethis:

 this.setState(currentState => ({ count: currentState.count + 1 }), () => {
    console.log(this.state.count);
});

Upvotes: 1

anvk
anvk

Reputation: 1201

It is pretty simple. When you run console.log(this.state.hero.Name); your state has not changed yet since this.setState() is async call. It means that everything what happens after its execution does not have an access to update state yet... To fix that you log console.log(temp); since it is an object you are going to use to update your this.state.hero

OR

you can use a callback for setState to get access to your state AFTER the async call finished its execution. Here is one of good articles about it setState callback

Upvotes: 1

Related Questions