score:637
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.
score:0
For dynamically setting state properties for form inputs and keeping them controlled you could do something like this:
const inputs = [
{ name: 'email', type: 'email', placeholder: "Enter your email"},
{ name: 'password', type: 'password', placeholder: "Enter your password"},
{ name: 'passwordConfirm', type: 'password', placeholder: "Confirm your password"},
]
class Form extends Component {
constructor(props){
super(props)
this.state = {} // Notice no explicit state is set in the constructor
}
handleChange = (e) => {
const { name, value } = e.target;
this.setState({
[name]: value
}
}
handleSubmit = (e) => {
// do something
}
render() {
<form onSubmit={(e) => handleSubmit(e)}>
{ inputs.length ?
inputs.map(input => {
const { name, placeholder, type } = input;
const value = this.state[name] || ''; // Does it exist? If so use it, if not use an empty string
return <input key={name} type={type} name={name} placeholder={placeholder} value={value} onChange={this.handleChange}/>
}) :
null
}
<button type="submit" onClick={(e) => e.preventDefault }>Submit</button>
</form>
}
}
score:1
In short, if you are using class component you have to initialize the input using state, like this:
this.state = { the_name_attribute_of_the_input: "initial_value_or_empty_value" };
and you have to do this for all of your inputs you'd like to change their values in code.
In the case of using functional components, you will be using hooks to manage the input value, and you have to put initial value for each input you'd like to manipulate later like this:
const [name, setName] = React.useState({name: 'initialValue'});
If you'd like to have no initial value, you can put an empty string.
score:2
This generally happens only when you are not controlling the value of the filed when the application started and after some event or some function fired or the state changed, you are now trying to control the value in input field.
This transition of not having control over the input and then having control over it is what causes the issue to happen in the first place.
The best way to avoid this is by declaring some value for the input in the constructor of the component. So that the input element has value from the start of the application.
score:2
Please try this code
import React from "react";
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { name: "" };
this.onFieldChange = this.onFieldChange.bind(this);
}
onFieldChange(e) {
this.setState({[e.target.name]: e.target.value});
}
render() {
return (
<form className="add-support-staff-form">
<input name="name" type="text" value={this.state.name} onChange={this.onFieldChange} />
</form>
);
}
}
export default MyForm;
score:3
In my case component was rerendering and throwing A component is changing an uncontrolled input of type checkbox to be controlled
error. It turned out that this behaviour was a result of not keeping true
or false
for checkbox checked state (sometimes I got undefined
). Here what my faulty component looked like:
import * as React from 'react';
import { WrappedFieldProps } from 'redux-form/lib/Field';
type Option = {
value: string;
label: string;
};
type CheckboxGroupProps = {
name: string;
options: Option[];
} & WrappedFieldProps;
const CheckboxGroup: React.FC<CheckboxGroupProps> = (props) => {
const {
name,
input,
options,
} = props;
const [value, setValue] = React.useState<string>();
const [checked, setChecked] = React.useState<{ [name: string]: boolean }>(
() => options.reduce((accu, option) => {
accu[option.value] = false;
return accu;
}, {}),
);
React.useEffect(() => {
input.onChange(value);
if (value) {
setChecked({
[value]: true, // that setChecked argument is wrong, causes error
});
} else {
setChecked(() => options.reduce((accu, option) => {
accu[option.value] = false;
return accu;
}, {}));
}
}, [value]);
return (
<>
{options.map(({ value, label }, index) => {
return (
<LabeledContainer
key={`${value}${index}`}
>
<Checkbox
name={`${name}[${index}]`}
checked={checked[value]}
value={value}
onChange={(event) => {
if (event.target.checked) {
setValue(value);
} else {
setValue(undefined);
}
return true;
}}
/>
{label}
</LabeledContainer>
);
})}
</>
);
};
To fix that problem I changed useEffect
to this
React.useEffect(() => {
input.onChange(value);
setChecked(() => options.reduce((accu, option) => {
accu[option.value] = option.value === value;
return accu;
}, {}));
}, [value]);
That made all checkboxes keep their state as true
or false
without falling into undefined
which switches control from React to developer and vice versa.
score:3
For people using Formik
, you need to add a default value for the specific field name
to the form's initialValues
.
score:3
I had the same problem. the problem was when i kept the state info blank
const [name, setName] = useState()
I fixed it by adding empty string like this
const [name, setName] = useState('')
score:5
An update for this. For React Hooks use const [name, setName] = useState(" ")
score:5
Simply create a fallback to '' if the this.state.name is null.
<input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
This also works with the useState variables.
score:5
I believe my input is controlled since it has a value.
Now you can do this two ways the best way is to have a state key to each input with 1 onChange handler. If you have checkboxes you will need to write a separate onChange handler.
With a Class component you would want to write it like this 👇
import React from 'react';
export default class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {
myFormFields: {
name: '',
dob: '',
phone: ''
}
}
this.onFormFieldChange = this.onFormFieldChange.bind(this)
}
// Always have your functions before your render to keep state batches in sync.
onFormFieldChange(e) {
// No need to return this function can be void
this.setState({
myFormFields: {
...this.state.myFormFields,
[e.target.name]: e.target.value
}
})
}
render() {
// Beauty of classes we can destruct our state making it easier to place
const { myFormFields } = this.state
return (
<form className="add-support-staff-form">
<input name="name" type="text" value={myFormFields.name} onChange={this.onFormFieldChange}/>
<input name="dob" type="date" value={myFormFields.dob} onChange={this.onFormFieldChange}/>
<input name="phone" type="number" value={myFormFields.phone} onChange={this.onFormFieldChange}/>
</form>
)
}
}
export default MyForm;
Hope that helps for a class but the most performative and what the newest thing the devs are pushing everyone to use is Functional Components. This is what you would want to steer to as class components don't intertwine well with the latest libraries as they all use custom hooks now.
To write as a Functional Component
import React, { useState } from 'react';
const MyForm = (props) => {
// Create form initial state
const [myFormFields, setFormFields] = useState({
name: '',
dob: '',
phone: ''
})
// Always have your functions before your return to keep state batches in sync.
const onFormFieldChange = (e) => {
// No need to return this function can be void
setFormFields({
...myFormFields,
[e.target.name]: e.target.value
})
}
return (
<form className="add-support-staff-form">
<input name="name" type="text" value={myFormFields.name} onChange={onFormFieldChange}/>
<input name="dob" type="date" value={myFormFields.dob} onChange={onFormFieldChange}/>
<input name="phone" type="number" value={myFormFields.phone} onChange={onFormFieldChange}/>
</form>
)
}
export default MyForm;
Hope this helps! 😎
score:6
Set a value to 'name' property in initial state.
this.state={ name:''};
score:7
If the props on your component was passed as a state, put a default value for your input tags
<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
score:8
When you use onChange={this.onFieldChange('name').bind(this)}
in your input you must declare your state empty string as a value of property field.
incorrect way:
this.state ={
fields: {},
errors: {},
disabled : false
}
correct way:
this.state ={
fields: {
name:'',
email: '',
message: ''
},
errors: {},
disabled : false
}
score:9
In my case, I was missing something really trivial.
<input value={state.myObject.inputValue} />
My state was the following when I was getting the warning:
state = {
myObject: undefined
}
By alternating my state to reference the input of my value, my issue was solved:
state = {
myObject: {
inputValue: ''
}
}
score:10
One potential downside with setting the field value to "" (empty string) in the constructor is if the field is an optional field and is left unedited. Unless you do some massaging before posting your form, the field will be persisted to your data storage as an empty string instead of NULL.
This alternative will avoid empty strings:
constructor(props) {
super(props);
this.state = {
name: null
}
}
...
<input name="name" type="text" value={this.state.name || ''}/>
score:20
Simple solution to resolve this problem is to set an empty value by default :
<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
score:28
I know others have answered this already. But a very important factor here that may help other people experiencing similar issue:
You must have an onChange
handler added in your input field (e.g. textField, checkbox, radio, etc). Always handle activity through the onChange
handler.
Example:
<input ... onChange={ this.myChangeHandler} ... />
When you are working with checkbox you may need to handle its checked
state with !!
.
Example:
<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >
Reference: https://github.com/facebook/react/issues/6779#issuecomment-326314716
score:75
Another approach it could be setting the default value inside your input, like this:
<input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
score:165
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.
Source: stackoverflow.com
Related Query
- React - changing an uncontrolled input
- React a component is changing an uncontrolled input of type checkbox to be controlled
- React form error changing a controlled input of type text to be uncontrolled
- A component is changing an uncontrolled input of type checkbox to be controlled in React JS
- React warning: "is changing an uncontrolled input of type hidden to be controlled" why?
- Warning: A component is changing a controlled input to be uncontrolled in React js
- React component is changing an uncontrolled input of type checkbox
- React input, I defined the state into initial state but still get warning changing uncontrolled to controlled input
- changing an uncontrolled input of type file in React
- Warning: A component is changing a controlled input to be uncontrolled input in react js
- React Formik Warning: A component is changing an uncontrolled input to be controlled
- React Input Warning: A component is changing a controlled input of type text to be uncontrolled
- React Hook Form and Material ui component-inputRef not working-A component is changing an uncontrolled input of type
- React App throwing error " Received NaN for the `value` attribute" and "A component is changing an uncontrolled input to be controlled"
- A component is changing an uncontrolled input of type text to be controlled error in ReactJS
- Material UI Select Component- A component is changing a controlled input of type text to be uncontrolled
- ReactJS Warning: TextField is changing an uncontrolled input of type text to be controlled
- formik warning, A component is changing an uncontrolled input of type text to be controlled
- ReactJS - Warning: A component is changing an uncontrolled input of type text to be controlled
- React-Mobx Warning: A component is changing an uncontrolled input
- Uncontrolled input React Hooks
- React - automatic submission of form upon changing input
- Uncontrolled Input to Controlled Input Warning in React Hook Form and Material UI's TextField
- A component is changing an uncontrolled input of type email to be controlled. Input elements should not switch from uncontrolled to controlled
- Changing the value of input field - React
- React changing input type via event
- React hook changing the state variable of wrong component when file input
- Should I ignore React warning: Input elements should not switch from uncontrolled to controlled?
- React: Warning, a component is changing an uncontrolled input to be controlled
- Why is my text not changing as I'm writing text to the input tag in React
More Query from same tag
- Express - return certain documents with named route parameters using axios
- Typing a custom useRef hook for any type of HTML element
- ClassName styles not working in react
- Cannot remove an event listener outside useEffect
- react use dangerouslySetInnerHTML to render json with html tags
- Removing component when clicked react
- Update List of users Table after POST fetch request
- Very strange CSS formatting with React app, major overlapping. How do I fix this?
- Pass data to parent without click
- Error: <Route> elements are for router configuration only and should not be rendered in react-router v4
- Enzyme: how to test a key down?
- React force componentDidMount
- react-table custom cell component that references several row properties
- Go to previous state or Re Render component for two different API functions in ReactJS
- javascript React Form onsubmit save submitted username
- Using App component as a home page in react (path "/")
- map through and object in react
- How can I use the regenerator-runtime polyfill conditionally?
- How to add vertical scrolling to reactstrap carousel slide content
- React typescript - How to handle multiple lists in a list
- Express - `req.body` is always empty
- Can't figure out how to change State in reducer without causing a mutation
- Javascript / React window.onerror fired twice
- How to fix unique "key" prop in ReactJS table?
- Why item delete from mongodb database but not in UI but after reload page, item delete from UI in react?
- Multiple call on same event
- How to test in JEST a request that downloads a file
- React dynamic tabindex creation
- How to show a message and delete it each time the route changes
- Styling in Material UI