Switching between controlled and uncontrolled input
See original GitHub issueI have set up an autocomplete with downshift and it works perfectly… except it gives me the following warning whenever i select an option.
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
As far as i can tell (by looking at what i set the value to before and after the selection) I am not changing the input to undefined or null (what most commonly causes this issue).
My downshift version is 1.31.16 My node version is 9.2.1 My npm version is 5.10.0 My material ui version is 1.2.3
My code is as follows
import React from 'react';
import PropTypes from 'prop-types';
import Downshift from 'downshift';
import TextField from '@material-ui/core/TextField';
import Paper from '@material-ui/core/Paper';
import Avatar from '@material-ui/core/Avatar';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
export class Autocomplete extends React.PureComponent {
static propTypes = {
items: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
onSelect: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
value: PropTypes.string,
inputDetails: PropTypes.shape({}).isRequired,
disconect: PropTypes.bool,
};
static defaultProps = {
value: '',
disconect: false,
}
getSuggestions = (items, inputValue, disconect) => {
if(disconect){return []}
return items.filter(suggestion => {
const keep = !inputValue ||
(suggestion.primary || '').toLowerCase().match(inputValue.toLowerCase()) ||
(suggestion.secondary && suggestion.secondary.toLowerCase().match(inputValue.toLowerCase()));
return keep;
});
}
render() {
const { onSelect, onChange, value, items, inputDetails, disconect } = this.props;
return (
<Downshift
style={{position: 'relative'}}
onChange={(selection, functions) => onSelect(selection, functions)}
onStateChange={({inputValue, type}) => {
if(type === '__autocomplete_change_input__' || type === '__autocomplete_click_item__'){
onChange((inputValue || ''));
}
}}
itemToString={(item) => { return item ? item.primary : ''}}
render={({
getInputProps,
getItemProps,
getLabelProps,
isOpen,
inputValue,
highlightedIndex,
selectedItem,
clearSelection,
}) => (
<div>
<TextField
InputProps={{
...getInputProps(),
placeholder: inputDetails.placeholder,
name: inputDetails.name,
id: inputDetails.id,
value,
}}
label={inputDetails.label}
fullWidth={inputDetails.fullWidth}
/>
{isOpen &&
<Paper style={{
position: 'absolute',
zIndex: 1,
}}>
{
this.getSuggestions(items, inputValue, disconect)
.map((item, index) => (
<MenuItem
{...getItemProps({
item: item,
})}
key={item._id}
style={{ height: 50 }}
>
{inputDetails.avitar &&
<Avatar>{item.primary[0]}</Avatar>
}
<ListItemText
primary={item.primary}
secondary={item.secondary}
/>
</MenuItem>
))
}
</Paper>
}
</div>
)}
/>
);
}
}
export default (Autocomplete);
Reproducing Bug To reproduce i type into the autofill field created and select an option from the suggestions that come up.
when a suggestion is selected it creates a warning that I am changing from a controlled to uncontrolled input.
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (3 by maintainers)
I figured it out. There were states (mostly initially) where I was passing
null
orundefined
values forselectedItem
andinputValue
. I changed it to pass""
in the cases where a value isnull
orundefined
which has resolved the console error. Might be good to update the docs to point this out more clearly.I got this error when I had:
but my item didn’t have
value
key. Switch toitem.name
(as my data hadname
key) helped