Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - changing an uncontrolled input

I have a simple react component with the form which I believe to have one controlled input:

import React from 'react';  export default class MyForm extends React.Component {     constructor(props) {         super(props);         this.state = {}     }      render() {         return (             <form className="add-support-staff-form">                 <input name="name" type="text" value={this.state.name} onChange={this.onFieldChange('name').bind(this)}/>             </form>         )     }      onFieldChange(fieldName) {         return function (event) {             this.setState({[fieldName]: event.target.value});         }     } }  export default MyForm; 

When I run my application I get the following warning:

Warning: MyForm 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

I believe my input is controlled since it has a value. I am wondering what am I doing wrong?

I am using React 15.1.0

like image 283
alexs333 Avatar asked May 25 '16 03:05

alexs333


People also ask

Is changing an uncontrolled input to be controlled?

The warning "A component is changing an uncontrolled input to be controlled" occurs when an input value is initialized to undefined but is later changed to a different value. To fix the warning, initialize the input value to an empty string, e.g. value={message || ''} .

How do you handle input change in React?

The standard way to handle form input value changes is to handle them with React. This is a technique called controlled components. We can create controlled components with input , textarea , and select elements. They maintain their own state, and updates are based on user input.

How do you set a default value for an uncontrolled field?

In the React rendering lifecycle, the value attribute on form elements will override the value in the DOM. With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value .

What is uncontrolled input in React?

What are uncontrolled components in React? Uncontrolled components are those for which the form data is handled by the DOM itself. “Uncontrolled” refers to the fact that these components are not controlled by React state. The values of the form elements are traditionally controlled by and stored on the DOM.


2 Answers

When you first render your component, this.state.name isn't set, so it evaluates to undefined or null, and you end up passing value={undefined} or value={null}to your input.

When ReactDOM checks to see if a field is controlled, it checks to see if value != null (note that it's !=, not !==), and since undefined == null in JavaScript, it decides that it's uncontrolled.

So, when onFieldChange() is called, this.state.name is set to a string value, your input goes from being uncontrolled to being controlled.

If you do this.state = {name: ''} in your constructor, because '' != null, your input will have a value the whole time, and that message will go away.

like image 24
Leigh Brenecki Avatar answered Sep 19 '22 11:09

Leigh Brenecki


I believe my input is controlled since it has a value.

For an input to be controlled, its value must correspond to that of a state variable.

That condition is not initially met in your example because this.state.name is not initially set. Therefore, the input is initially uncontrolled. Once the onChange handler is triggered for the first time, this.state.name gets set. At that point, the above condition is satisfied and the input is considered to be controlled. This transition from uncontrolled to controlled produces the error seen above.

By initializing this.state.name in the constructor:

e.g.

this.state = { name: '' }; 

the input will be controlled from the start, fixing the issue. See React Controlled Components for more examples.

Unrelated to this error, you should only have one default export. Your code above has two.

like image 72
fvgs Avatar answered Sep 18 '22 11:09

fvgs