6

I use React + TypeScript + Mobx. I made the form with input, everything is working, but the browser gives an error. What am I doing wrong?

Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.

Form:

@observer
export class SearchForm extends React.Component {

    @observable
    private _inputText: string;

    submitForm = (event: SyntheticEvent<HTMLFormElement>) => {
    event.preventDefault();
    }

    render() {
      return (
        <form onSubmit={this.submitForm}>
          <InputField
            value={this._inputText}
            onChange={action((value: string) => this._inputText = value)}
          />
       </form>
    );}}

Input:

interface Props {
  value: string;
  onChange: (inputText: string) => void;
}

@observer
export class InputField extends React.Component<Props> {

  onChange = (event: SyntheticEvent<HTMLInputElement>) => {
  this.props.onChange(event.currentTarget.value);
  }

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.props.value}
          onChange={this.onChange}
        />
     </div>
   );
 }
}
cooperJCW
  • 65
  • 4

1 Answers1

4

React's inputs are controlled/uncontrolled based on the presence of the value prop on the input. You're passing the value prop, but _inputText starts as undefined. And when input's value starts undefined, React will always start the input in uncontrolled mode.

Once you type in the input, _inputText is no longer undefined, and the input flips to controlled mode, and you get the warning.

For your case, the fix is simple; just initialize _inputText to the empty string:

@observable
private _inputText: string = '';

You could also tweak your <InputField /> to force undefined value props to be the empty string:

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.props.value == null ? '' : this.props.value}
          onChange={this.onChange}
        />
     </div>
   );
 }
noetix
  • 4,773
  • 3
  • 26
  • 47
adharris
  • 3,591
  • 1
  • 21
  • 18