question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Switching between controlled and uncontrolled input

See original GitHub issue

I 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:closed
  • Created 5 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

21reactions
eriklharpercommented, Jan 18, 2019

I figured it out. There were states (mostly initially) where I was passing null or undefined values for selectedItem and inputValue. I changed it to pass "" in the cases where a value is null or undefined which has resolved the console error. Might be good to update the docs to point this out more clearly.

15reactions
partyka1commented, Feb 28, 2019

I got this error when I had:

<Downshift itemToString={(item) => (item ? item.value : "")}>

but my item didn’t have value key. Switch to item.name(as my data had name key) helped

Read more comments on GitHub >

github_iconTop Results From Across the Web

javascript - React - changing an uncontrolled input
I believe my input is controlled since it has a value. For an input to be controlled, its value must correspond to that...
Read more >
A component is changing an uncontrolled input to be ...
A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined ......
Read more >
A component is changing an uncontrolled input to be ...
The warning "A component is changing an uncontrolled input to be controlled" occurs when an input value is initialized to undefined but is...
Read more >
Solve - A component is changing an uncontrolled input to ...
The warning : A component is changing an uncontrolled input to be controlled . This is likely caused by the value changing from...
Read more >
Uncontrolled Components
In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found