Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A component is changing an uncontrolled Autocomplete to be controlled

Tags:

Can you tell me that why I'm getting error "A component is changing an uncontrolled Autocomplete to be controlled. Elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled Autocomplete element for the lifetime of the component."

component :

 function AutoComplete(props) {    const defaultProps = {     options: props.options,     getOptionLabel: option => option.name,   };    const handleChange = (e, value) => {     props.onChange(value);   };    return (     <Autocomplete       {...defaultProps}       renderInput={params => (         <TextField {...params} label={props.label} margin="normal" />       )}       onChange={handleChange}       value={props.value}     />   ); }  

calling autocomplte:

               <Controller                 control={control}                 name = 'country'                 as = {                   <AutoComplete                     options={countryOptions}                     onChange={selectCountryHandler}                     label="Country"                     value={selectedCountry  || ''}                   />                 } /> 

how can I solve this error?

like image 876
kinza Avatar asked Aug 07 '20 05:08

kinza


People also ask

Why is a component changing an uncontrolled input to be controlled?

The 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.

How to prevent the autocomplete component from going into uncontrolled mode?

When no value is selected, you need to add || null to prevent the Autocomplete going into uncontrolled mode: If you pass value= {undefined} to the Autocomplete component, it will start in "uncontrolled" mode, meaning it keeps its own internal state. Then if you later supply a value it raises the "A component is changing" error.

Why is my React component changing an uncontrolled input?

If you are starting with handling user inputs in React, you might have come across the following 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.

How to switch from uncontrolled elements to controlled elements?

Elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled Select element for the lifetime of the component. The nature of the state is determined during the first render. It's considered controlled if the value is not undefined.


2 Answers

You ensured that the value property never had been undefined, but you had to do same for inputValue.

  1. the "value" state with the value/onChange props combination. This state represents the value selected by the user, for instance when pressing Enter.
  2. the "input value" state with the inputValue/onInputChange props combination. This state represents the value displayed in the textbox.

⚠️ These two state are isolated, they should be controlled independently.

Component becomes uncontrolled when inputValue property is undefined, and vice versa.

If in the following example you delete an empty string from React.useState('') you'll get the same error message because inputValue during first render is undefined.

import React from 'react' import TextField from '@material-ui/core/TextField' import Autocomplete from '@material-ui/lab/Autocomplete'  const options = ['Option 1', 'Option 2']  export default function AutocompleteLab() {   const [value, setValue] = React.useState(options[0])   const [inputValue, setInputValue] = React.useState('')    return (     <div>       <div>{`value: ${value !== null ? `'${value}'` : 'null'}`}</div>       <div>{`inputValue: '${inputValue}'`}</div>       <br />       <Autocomplete         value={value}         onChange={(_, newValue) => {           setValue(newValue)         }}         inputValue={inputValue}         onInputChange={(_, newInputValue) => {           setInputValue(newInputValue)         }}         options={options}         style={{ width: 300 }}         renderInput={(params) => <TextField {...params} label="Name" variant="outlined" />}       />     </div>   ) }  
like image 80
Spatz Avatar answered Sep 26 '22 09:09

Spatz


I solved this by removing the default value.

             <Autocomplete                 multiple                 id="multiple-limit-tags"                 options={(option) => option.label}                 getOptionLabel={(option) => option}                 // defaultValue={options || []}                 renderInput={(params) => <TextField {...params} label="My Label" />}                          /> 

It wasn't obvious how to solve this, and the documentation doesn't help much either. I find it curious that a copy-pasted example from the documentation results in this error. I guess the example works because the choices are hard-coded.

like image 20
Emanuel Lindström Avatar answered Sep 26 '22 09:09

Emanuel Lindström