How to fix Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`. in React
This React warning appears when you set a checked prop on a checkbox or radio button without providing an onChange event handler. React treats inputs with a checked prop as controlled components, which require onChange handlers to update their state.
Quick fix
Fixes Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
import { useState } from 'react';
function MyComponent() {
const [isChecked, setIsChecked] = useState(false);
return (
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
);
}- Add an onChange handler for controlled inputs
- Use defaultChecked for uncontrolled inputs
- Add readOnly for truly read-only checkboxes
- Fix mixed controlled/uncontrolled patterns
import { useState } from 'react';function MyComponent() {const [isChecked, setIsChecked] = useState(false);return (<inputtype="checkbox"checked={isChecked}onChange={(e) => setIsChecked(e.target.checked)}/>);}Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
What this error means
This warning occurs when React detects a checkbox or radio button with a checked prop but no corresponding onChange handler. In React's component model, form inputs can be either controlled or uncontrolled. When you provide a checked prop with a boolean value, React treats the input as a controlled component, meaning React is responsible for managing its state. Controlled components require an onChange handler to update the backing state when the user interacts with the input. Without this handler, the checkbox becomes effectively read-only - users can click it, but the visual state won't change because nothing is updating the checked value. This creates a confusing user experience where the interface appears broken. React issues this warning to alert you that you've created a controlled component pattern but haven't completed the implementation by providing the state update mechanism.
Typical symptoms
- Console warning: "You provided a checked prop to a form field without an onChange handler"
- Checkbox or radio button appears to not respond to clicks
- Input element shows the initial checked state but won't toggle when clicked
- Warning mentions "This will render a read-only field"
- Suggestion to use defaultChecked or add onChange/readOnly in the warning message
Common causes
- Setting checked={someBoolean} on a checkbox without an onChange handler
- Converting an uncontrolled input to controlled by adding checked prop without updating the event handling
- Copy-pasting controlled component code but forgetting the onChange handler
- Attempting to create a read-only checkbox but using checked instead of readOnly
- Using checked prop when defaultChecked was the intended choice for an uncontrolled input
How to fix "Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`."
If you want a controlled checkbox where React manages the state, add both state and an onChange handler:
import { useState } from 'react';
function MyComponent() {
const [isChecked, setIsChecked] = useState(false);
return (
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
);
}For radio buttons:
function RadioExample() {
const [selected, setSelected] = useState('option1');
return (
<div>
<input
type="radio"
checked={selected === 'option1'}
onChange={() => setSelected('option1')}
/>
<input
type="radio"
checked={selected === 'option2'}
onChange={() => setSelected('option2')}
/>
</div>
);
}This is the recommended approach when you need to react to changes, validate input, or synchronize with other components.
If you only need to set an initial value and don't need React to track changes, use defaultChecked instead:
function MyComponent() {
return (
<input
type="checkbox"
defaultChecked={true}
/>
);
}With defaultChecked, the browser manages the input's state internally. Access the value when needed using refs:
import { useRef } from 'react';
function FormExample() {
const checkboxRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(checkboxRef.current.checked);
};
return (
<form onSubmit={handleSubmit}>
<input
type="checkbox"
ref={checkboxRef}
defaultChecked={false}
/>
<button type="submit">Submit</button>
</form>
);
}This approach works well for simple forms where you only need the final value.
If you want to display a checkbox state without allowing user interaction, use the readOnly prop:
function DisplayOnly({ isFeatureEnabled }) {
return (
<input
type="checkbox"
checked={isFeatureEnabled}
readOnly
/>
);
}The readOnly prop explicitly tells React this is intentionally non-interactive, which suppresses the warning. Note that readOnly inputs:
- Still submit with forms (unlike disabled inputs)
- Can receive focus
- Show the correct visual state
- Don't trigger onChange events
Alternatively, if the checkbox should be completely non-interactive and not submit with forms, use disabled:
<input
type="checkbox"
checked={value}
disabled
/>Sometimes this warning appears when state initialization allows undefined values:
// WRONG - checked becomes undefined initially
function BadExample() {
const [isChecked, setIsChecked] = useState();
return (
<input
type="checkbox"
checked={isChecked} // undefined at first, then boolean
onChange={(e) => setIsChecked(e.target.checked)}
/>
);
}Fix by providing an initial boolean value:
// CORRECT
function GoodExample() {
const [isChecked, setIsChecked] = useState(false);
return (
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
);
}If the initial value comes from props that might be undefined, use nullish coalescing:
function ComponentWithProps({ initialChecked }) {
const [isChecked, setIsChecked] = useState(initialChecked ?? false);
return (
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
);
}Advanced notes
When to use controlled vs uncontrolled:
Controlled components are preferred when you need to:
- Validate input as the user types
- Conditionally enable/disable form submission
- Enforce specific input formats
- Synchronize the same data across multiple components
- Trigger side effects on value changes
- Implement complex form logic with interdependent fields
Uncontrolled components with defaultChecked are suitable when:
- Building simple forms that only need values on submit
- Working with large forms where re-rendering on every change is expensive
- Integrating with non-React code that expects direct DOM access
- Implementing file inputs (which must be uncontrolled)
Event handler patterns:
For multiple checkboxes with shared state, use a dynamic handler:
function MultiCheckbox() {
const [options, setOptions] = useState({
feature1: false,
feature2: true,
feature3: false,
});
const handleChange = (name) => (e) => {
setOptions(prev => ({
...prev,
[name]: e.target.checked
}));
};
return (
<>
<input type="checkbox" checked={options.feature1} onChange={handleChange('feature1')} />
<input type="checkbox" checked={options.feature2} onChange={handleChange('feature2')} />
<input type="checkbox" checked={options.feature3} onChange={handleChange('feature3')} />
</>
);
}Form libraries: Consider using form libraries like React Hook Form or Formik for complex forms. These libraries handle controlled/uncontrolled patterns automatically and provide validation, error handling, and submission logic out of the box.
TypeScript typing: When working with TypeScript, properly type your event handlers:
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setIsChecked(event.target.checked);
};Frequently asked questions
- What does "Warning: Failed prop type: You provided a `checked` prop to a form fie" mean?
- This warning occurs when React detects a checkbox or radio button with a checked prop but no corresponding onChange handler. In React's component model, form inputs can be either controlled or uncontrolled. When you provide a checked prop with a boolean value, React treats the input as a controlled component, meaning React is responsible for managing its state.
- How do I fix "Warning: Failed prop type: You provided a `checked` prop to a form fie"?
- This React warning appears when you set a checked prop on a checkbox or radio button without providing an onChange event handler. React treats inputs with a checked prop as controlled components, which require onChange handlers to update their state.
- What causes "Warning: Failed prop type: You provided a `checked` prop to a form fie"?
- Setting checked={someBoolean} on a checkbox without an onChange handler Converting an uncontrolled input to controlled by adding checked prop without updating the event handling Copy-pasting controlled component code but forgetting the onChange handler
- Is the "Warning: Failed prop type: You provided a `checked` prop to a form fie" error serious?
- It is a low-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐React Official Documentation
- ๐React Official Docs: Input Components(Official Docs)
- ๐Form elements should be either controlled or uncontrolled(Official Docs)