61

I am trying to change the value of Select input and then i am getting the following warning in the console.

index.js:1446 Warning: 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.

But i am updating the state in correct way only , Here is my code

 <Select
        value={props.selectedService}
        onChange={props.handleSelectChange}
        inputProps={{
          name: 'selectedService',            
        }}
   >
   <MenuItem value="">
     <em>None</em>
   </MenuItem>
   <MenuItem value="Dry Cleaning">Dry Cleaning</MenuItem>
   <MenuItem value="Washing and Ironing">Washing and Ironing</MenuItem>
   <MenuItem value="Rolling">Rolling</MenuItem>
 </Select>

And the handleselectchange functionality is here .

handleSelectChange = ({target: {name,value}}) => { 
  console.log(name);
  console.log(value); 
  this.setState({ 
    serviceRequest: { 
      selectedService: value 
    } 
  }); 
}

And state object declaration is below

state = {
    open: false,
    selectedDate: new Date(),
    selectedTime : new Date(),
    mailDetails :{
      name:"",
      email:'',
      message:''
    },
    serviceRequest: {
      name: '',
      email: '',
      mobileNumber:'',
      address:'',
      landMark:'',
      selectedService:''
  }
};

Can anyone please suggest what is the issue?

Spatz
  • 18,640
  • 7
  • 62
  • 66
Roster
  • 1,764
  • 6
  • 17
  • 36

4 Answers4

107

Uncontrolled here means you may be setting the value of the Select component to undefined, this is because value={props.selectedValue} here. In this the props or selectedValue may come null so it turns out to be a uncontrolled component in that.

To solve the warning you can add condition to check null and set default value.

value={props.selectedValue ? props.selectedValue : " "}

Or for easy syntax using nullish coalescing operator (??)

value={props.selectedValue ?? " "}

Raj Saraogi
  • 1,780
  • 1
  • 13
  • 21
  • 7
    This will create an issue: You must control your input, or make it a controlled component. Generally, from my personal experience, in React, you want to avoid controlled Input as much as you can. A controlled input generally puts more verbose logic into your code and if you have no need for extra functionalities like validation, it is redundant code. Besides, a controlled component is always less performant than an uncontrolled one due to having to deal with state. This is noticeable especially when you have a lot of fields in your form. – allicanseenow Mar 02 '20 at 13:28
  • @allicanseenow I prefer having everything in my global app state, to pick whatever is needed from it when I 'validate'. For this specific issue, I just added a default value to avoid the `undefined` step: `const {selectedValue = ''} = props;` – Chris Feb 22 '21 at 21:40
14

the same of the accepted answer but check for undefined and provide default value with nullish coalescing operator (??)

value={props.selectedValue ?? ""}
mindlid
  • 1,679
  • 14
  • 17
7

With my case I had to set a default value on the Controller component

<Controller
  name="stackoverflow"
  rules={{ required: 'Please select a stackoverflow' }}
  control={control}
  defaultValue={''} // <---------- HERE
  render={({ field, fieldState }) => {
    return (
      <FormControl>
        <InputLabel id="stackoverflow-label">stackoverflow</InputLabel>
        <Select
          id="stackoverflow-select"
          label="stackoverflow"
          labelId="stackoverflow-id"
          error={!!fieldState.error}
          {...field}
        >
         <MenuItem value={i ?? ''} key={i}>
                {i}
         </MenuItem>
        </Select>
        {fieldState.error ? (
          <FormHelperText error>
            {fieldState.error?.message}
          </FormHelperText>
        ) : null}
      </FormControl>
    );
  }}
/>
Mnai
  • 407
  • 3
  • 8
  • 1
    It worked for me with `FormControlLabel defaultValue={false}` – testing_22 Jan 24 '23 at 05:04
  • it worked for me with `` but I still think nowhere in that syntax should mui conclude this is an attempt to turn into a controlled component. other controls (such as TextField) work with undefined 'defaultValue' just fine – Nir O. Feb 11 '23 at 12:27
-2

You can only change

value={props.selectedService} 

to

value={props.selectedService ? props.selectedService : ""}

 <Select
    ***value={props.selectedService ? props.selectedService : ""}***
    onChange={props.handleSelectChange}
    inputProps={{
      name: 'selectedService',            
    }}
  >
   <MenuItem value="">
     <em>None</em>
   </MenuItem>
   <MenuItem value="Dry Cleaning">Dry Cleaning</MenuItem>
   <MenuItem value="Washing and Ironing">Washing and Ironing</MenuItem>
   <MenuItem value="Rolling">Rolling</MenuItem>
 </Select>