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>
   );
 }
}
3
  • Your input is in fact controlled, so I don't see the problem. Maybe you have another input element somewhere in your code, that is not controlled? Commented Jun 6, 2018 at 8:43
  • No, i have only one input in project Commented Jun 6, 2018 at 9:20
  • Can you set up a plunkr, codepen, or similar to reproduce this problem? Commented Jun 6, 2018 at 9:29

1 Answer 1

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>
   );
 }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.