How to fix You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`. in React

ReactBEGINNERMEDIUMUpdated Dec 8, 2025ยท 138 views

React warns when you provide a value prop to a form field without an onChange handler. This creates a read-only field that cannot be edited. Fix it by adding an onChange handler, using defaultValue instead, or explicitly setting the readOnly prop.

Quick fix

Fixes You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

import { useState } from 'react';

function MyForm() {
  const [email, setEmail] = useState('');
  
  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}
  1. Add onChange handler with state update
  2. Switch to defaultValue for uncontrolled inputs
  3. Add readOnly prop for display-only fields
  4. Initialize state with proper default values
react โ€” error
import { useState } from 'react';
function MyForm() {
const [email, setEmail] = useState('');
return (
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
);
}
You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

What this error means

This warning occurs when you set the value prop on an input element without providing an onChange event handler. In React, controlled components require both a value and an onChange handler to function properly. When you pass a value prop, React expects you to manage that value through state and update it via onChange events. Without an onChange handler, the input becomes read-only because React has no way to update the controlled value when users type. This creates a confusing user experience where the input appears editable but doesn't respond to user input. React displays this warning to help you identify the issue before users encounter the broken behavior. This warning is distinct from the "uncontrolled to controlled" warning, which occurs when an input switches between having undefined/null values and defined values. The "controlled without onChange" warning specifically targets inputs that have a defined value but lack the change handler needed to update that value.

Typical symptoms

  • Console warning: "You provided a value prop to a form field without an onChange handler"
  • Input field displays initial value but doesn't respond when users type
  • Text cursor appears in input but typed characters don't show up
  • Input appears interactive but behaves like a read-only field
  • Form field shows value from state but can't be edited
  • React DevTools shows value prop set but no onChange event handler
  • Keyboard input into the field has no visible effect

Common causes

  1. Setting value prop on input without corresponding onChange handler
  2. Passing state variable to value prop but forgetting to update state on user input
  3. Converting uncontrolled input to controlled by adding value prop without onChange
  4. Copy-pasting input code and removing onChange handler by mistake
  5. Using value prop when defaultValue would be more appropriate for the use case
  6. Attempting to create read-only input without using readOnly prop explicitly
  7. Misunderstanding the difference between controlled and uncontrolled components
  8. Using third-party form libraries incorrectly that handle onChange differently

How to fix "You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`."

1Add onChange handler with state update

The standard solution is to add an onChange handler that updates the state backing the input value. This creates a proper controlled component:

jsx
import { useState } from 'react';

function MyForm() {
  const [email, setEmail] = useState('');
  
  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}

The onChange handler receives a synthetic event, and e.target.value contains the new input value. Update your state synchronously in the handler so React re-renders with the new value.

2Switch to defaultValue for uncontrolled inputs

If you don't need to control the input value through React state, use defaultValue instead of value. This creates an uncontrolled component that manages its own state:

jsx
function MyForm() {
  return (
    <input
      type="text"
      defaultValue="Initial text"
      name="username"
    />
  );
}

With defaultValue, React sets the initial value but doesn't control subsequent changes. Access the value later via a ref or form submission event. This approach works well for simple forms where you don't need real-time validation or derived state.

3Add readOnly prop for display-only fields

If the field genuinely should not be editable, add the readOnly prop to explicitly declare this intent and suppress the warning:

jsx
function UserProfile({ username }) {
  return (
    <input
      type="text"
      value={username}
      readOnly
      className="bg-gray-100"
    />
  );
}

The readOnly attribute makes the semantic purpose clear and tells React you intentionally want a non-editable field. Consider using styled text or a <p> tag instead if no input interaction is needed.

4Initialize state with proper default values

Ensure your state is never undefined or null if you're using controlled components. Always initialize with an appropriate default:

jsx
// Good - always defined
const [text, setText] = useState('');
const [count, setCount] = useState(0);
const [selected, setSelected] = useState('option1');

// Bad - undefined causes issues
const [text, setText] = useState();
const [data, setData] = useState(null); // If used immediately

For values that load asynchronously, use empty string, empty array, or provide a loading state until data arrives. Use the value ?? '' pattern if the value might be undefined or null.

5Check for conditional onChange assignment

Verify you're not conditionally setting onChange in a way that causes it to be undefined:

jsx
// Problem - onChange only set sometimes
<input
  value={text}
  {...(someCondition && { onChange: handleChange })}
/>

// Fix - always provide onChange or use readOnly
<input
  value={text}
  onChange={someCondition ? handleChange : () => {}}
  readOnly={!someCondition}
/>

Inspect any prop spreading or conditional logic that might cause onChange to be missing. Ensure the handler is always present for controlled inputs.

6Verify third-party component compatibility

If using form libraries like React Hook Form, Formik, or React Bootstrap Typeahead, ensure you're passing the onChange handler correctly:

jsx
// React Hook Form example
import { useForm } from 'react-hook-form';

function MyForm() {
  const { register } = useForm();
  
  return (
    <input
      type="text"
      {...register('fieldName')} // Spreads value, onChange, etc.
    />
  );
}

Consult the library's documentation for the correct pattern. Some libraries provide custom onChange prop names or handle state management differently. Check GitHub issues for known compatibility problems.

Advanced notes

React's controlled component pattern ensures the component state is the "single source of truth" for form values. This enables features like real-time validation, conditional logic, and synchronized multi-field behavior, but requires proper onChange handling.

For complex forms with many fields, consider using a form management library like React Hook Form or Formik that handles the onChange boilerplate automatically. These libraries use refs and uncontrolled components internally for better performance while providing a controlled-like API.

The warning fires during development but is suppressed in production builds. However, the underlying issue (non-functional inputs) persists, so always fix the warning during development.

If you need a hybrid approach, you can start with an uncontrolled component using defaultValue and later "upgrade" to a controlled component by adding state and onChange when you need more control. Just avoid switching back and forth during a component's lifecycle.

For accessibility, read-only inputs should still be keyboard-accessible and properly labeled. Consider using aria-readonly and ensure screen readers announce the read-only state correctly.

Frequently asked questions

What does "You provided a `value` prop to a form field without an `onChange` hand" mean?
This warning occurs when you set the value prop on an input element without providing an onChange event handler. In React, controlled components require both a value and an onChange handler to function properly. When you pass a value prop, React expects you to manage that value through state and update it via onChange events.
How do I fix "You provided a `value` prop to a form field without an `onChange` hand"?
React warns when you provide a value prop to a form field without an onChange handler. This creates a read-only field that cannot be edited. Fix it by adding an onChange handler, using defaultValue instead, or explicitly setting the readOnly prop.
What causes "You provided a `value` prop to a form field without an `onChange` hand"?
Setting value prop on input without corresponding onChange handler Passing state variable to value prop but forgetting to update state on user input Converting uncontrolled input to controlled by adding value prop without onChange
Is the "You provided a `value` prop to a form field without an `onChange` hand" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading