javascriptreactjswarningsuserformreact-component

(ReactJS) "Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined ..."


The UserForm which is controlled by another controller complains on console as

"Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components input span li ul..."**

This is the component code:

export default({user}) => {
  if(!user) {
    return <div></div>
  } else {
    const [name,setName] = useState(user.name|| "")
    useEffect(() => {
      setName(user.name);
    }, [user])
              
    return <form>
             <fieldset> 
               <legend> Edit  {user.name }</legend>
               <p> 
                 <label htmlFor={"name"}> Name  </label>
                 <input  id="name" value={name || ""} onChange={e => setName(e.target.value)} />
               </p> 
             </fieldset>
           </form>
  }
}

I tried all fixes suggested on other stackoverflow answers but still gives warning.
Is there something I migth missing?


Solution

  • Actually in react when you are facing this, it is an error of controlled and uncontrolled components, in Simple words: controlled components: are the components which uses states to change their values. Example:

    <input
    onChange={(e)=>{whatever!}
    value={from your state}
    />
    

    while in uncontrolled components states are not involved that much you can simply use defaultValue or ref. Example:

    <input
    defaultValue={from your state or from anywhere}
    />
    

    Remember: if you are using both value and defaultValue it will give you the error because we can't use value of controlled component and defaultValue of uncontrolled component together.

    Hint: you need to choose between controlled and uncontrolled components, so using ref would be solution for it. or Changing value to defaultValue will resolve it.

    Note:

    defaultValue is only for the initial load. If you want to initialise the input then you should use defaultValue, but if you want to use state to change the value then you need to use value. Read this for more React input defaultValue doesn't update with state

    I used the below way in the input to get rid of that warning,define the value property by using Short-circuit evaluation like this:

    value={this.state.fields.name || ''}   // (undefined || '') = ''
    

    Another Approach

    The reason is, in state you defined:

    this.state = { fields: {} }
    

    fields as a blank object, so during the first rendering this.state.fields.name will be undefined, and the input field will get its value as:

    value={undefined}
    

    Because of that, the input field will become uncontrolled.

    Once you enter any value in input, fields in state gets changed to:

    this.state = { fields: {name: 'xyz'} }
    

    And at that time the input field gets converted into a controlled component; that's why you are getting the error:

    A component is changing an uncontrolled input of type text to be controlled.

    Possible Solution:

    1- Define the fields in state as:

    this.state = { fields: {name: ''} }