6

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;
1

1 Answer 1

11

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
  }
}));
Sign up to request clarification or add additional context in comments.

1 Comment

I understood THANK you so much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.