Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - Change a JSON Object in setState

Tags:

reactjs

I have a form with three fields, the handleChange method works in the first field (DateOfBirth) but not in the (Id1) and (Id2) fields.

For some reason setState return this error when i try to change the value of the (Id1||Id2) fields.

"A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component"

import React, { Component } from 'react';

class Form extends React.Component {

    constructor(props){
        super(props);
        this.state = { DateOfBirth:'1990-01-24', Metadata: {Id1:'33813518109', Id2:'John Doe'}}
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) { 
        const target = event.target;
        const name = target.name;        
        var value = target.value;         

        if(name === "Id1" || name === "Id2")            
            this.setState({Metadata:{[name]: value}});     
        else
            this.setState({[name]: value});
    }  

    render() { 
        return (             
            <div>
                <form onSubmit={this.handleSubmit}>                                          
                    <input name="DateOfBirth" type="date" onChange={this.handleChange} value={this.state.DateOfBirth} />                                           
                    <input name="Id1" type="text" onChange={this.handleChange} value={this.state.Metadata.Id1} />   
                    <input name="Id2" type="text" onChange={this.handleChange} value={this.state.Metadata.Id2} />
                </form>
            </div>            
        );
    }
}

export default Form;
like image 354
user2546477 Avatar asked Mar 18 '18 14:03

user2546477


People also ask

How do you update setState in React?

Before updating the value of the state, we need to build an initial state setup. Once we are done with it, we use the setState() method to change the state object. It ensures that the component has been updated and calls for re-rendering of the component.

How do you update an object in an array in React?

To update an array of objects state in React: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met. Update the properties of the object that matches the condition.


1 Answers

From react docs.

The output of the updater is shallowly merged with prevState.

Which means when you do

// name === 'Id1'
// value === 'dummy'
this.setState({Metadata:{[name]: value}});

then Metadata key in the state will have this shape:

{
  Metadata: {
    Id1: "dummy"
  }
}

Do you see the problem? Now input with Id2 receives as value undefined (this.state.Metadata.Id2 doesn't exist) which will make react throw an error about an uncontrolled component.

What you need to do to fix it is to make a full copy of nested object properties:

this.setState(prevState => ({
  Metadata:{
    ...prevState.Metadata,
    [name]: value
  }
}));
like image 138
Tomasz Mularczyk Avatar answered Nov 10 '22 16:11

Tomasz Mularczyk