简体   繁体   中英

React Component State Being Reset to Default

I am trying to track a form in this.state with event handlers on the inputs, but for some reason this.state is being reset back to its default state when the event handler tries to update it. This is an example of what the Component looks like.

class ExampleReport extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            reportDetails: null,
            report: this.props.report,
            form: {}
        }
        this.textInputHandler = this.textInputHandler.bind(this)
    }

    textInputHandler(e) {
        var reportForm = this.state.form;
        var target = e.target;
        var name = target.className;
        var value = target.value;
        reportForm[name] = value;
        this.setState({ form: reportForm })
    }

    render(){
      return(
        <form>
          <input className="example" type="text" onChange={(e) => {this.textInputHandler(e)}} />
        </form>
      )
    }
}

Before textInputHandler is called, this.state has an object and array stored in it, but once setState is called they are reset back to the default in the constructor. On subsequent updates to the text input this.state.form persists but everything else is reset. How can I prevent this from happening?

UPDATE

After trying some of the solutions suggested below I went back and logged this.state at just about every possible point and found that it is reset even before setState() is being called in the input handler.

You forget about input value and update state by ref (make mutation).

 class ExampleReport extends React.Component { constructor(props) { super(props) this.state = { reportDetails: null, report: this.props.report, form: { example: '', }, } this.textInputHandler = this.textInputHandler.bind(this) } textInputHandler(e) { const { target: { name, value } } = e; this.setState(prevState => ({ ...prevState, form: { ...prevState.form, [name]: value, }, })); } render() { const { form: { example } } = this.state; return ( <form> <input className="example" type="text" name="example" value={example} onChange={this.textInputHandler} /> </form> ) } }

Once way to solve this would be like below, spreading reportForm in a new object

  textInputHandler(e) {
        var reportForm = this.state.form;
        var target = e.target;
        var name = target.className;
        var value = target.value;
        reportForm[name] = value;
        this.setState({ form: { ...reportForm } }) // <----------------------
    }

However you may want to use more declarative solution as provided by Kirill but without unnecessary state changes

  textInputHandler(e) {
        const { className: name, value } = e.target;
        this.setState(prevState => { form: { ...prevState.form, [name]: value } }) // <----------------------
    }

try changing your onChange to this

onChange={this.textInputHandler}

like how they have it in the react documentation EX)

<input type="text" value={this.state.value} onChange={this.handleChange} />

then do the spreading stuff don't add, e.preventDefault because that only works for submitting

Look at Krill answer he has everything you need on there compare it to yours from the top, you have a lot of stuff missing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM