skip to Main Content

I have a situation where I want to set the default value of a radio group as a side effect of a deferred call. However, it would appear that the defaultValue property is ignored on a state update, and I’m at a loss to understand why. Here is a simple example, which I ran through https://playcode.io/react:

import React from 'react';

export function App(props) {
  const [defaultValue, setDefaultValue] = React.useState(1);

  React.useEffect(() => {
    setDefaultValue(2);
  });

  console.log(defaultValue);

  return (
    <div className='App'>
      <input type="radio" name="whatever" value="0" defaultChecked={defaultValue === 0}></input>Value 0
      <input type="radio" name="whatever" value="1" defaultChecked={defaultValue === 1}></input>Value 1
      <input type="radio" name="whatever" value="2" defaultChecked={defaultValue === 2}></input>Value 2
    </div>
  );
}

As you can see, the initial state of the default value is 1, which is then changed to 2 once useEffect() takes place.

I did manage to work around this by setting the "checked" property instead and putting in an onChange handler to store the value, but I’m really curious as to why defaultChecked isn’t working when the state changes.

2

Answers


  1. If you want the defaultValue state to determine the selected radio button and react to state updates, you need to use the checked property instead of defaultChecked. Here’s how you can adjust your code:

    import React from 'react';
    
    export function App(props) {
      const [defaultValue, setDefaultValue] = React.useState(1);
    
      React.useEffect(() => {
        setDefaultValue(2); // Update defaultValue after mount
      }, []);
    
      console.log(defaultValue);
    
      return (
        <div className='App'>
          <input
            type="radio"
            name="whatever"
            value="0"
            checked={defaultValue === 0}
            onChange={() => setDefaultValue(0)}
          />Value 0
          <input
            type="radio"
            name="whatever"
            value="1"
            checked={defaultValue === 1}
            onChange={() => setDefaultValue(1)}
          />Value 1
          <input
            type="radio"
            name="whatever"
            value="2"
            checked={defaultValue === 2}
            onChange={() => setDefaultValue(2)}
          />Value 2
        </div>
      );
    }
    
    Login or Signup to reply.
  2. This is because the defaultChecked property in React only works when the component is initially rendered and is ignored on subsequent renders or state updates.

    The defaultChecked attribute is used to set the initial checked state of an input element. This is a static initialization property—it only affects the DOM element on its first render. React doesn’t update the defaultChecked attribute when the component is re-rendered after a state or prop change. Instead, React expects you to control the checked state explicitly via the checked property if you want to dynamically change the value.

    The reason why defaultChecked isn’t working when the state changes as per your example.

    1. Initially, defaultValue is 1, so the second radio input’s defaultChecked evaluates to true during the initial render.

    2. On the next render (after the useEffect sets defaultValue to 2), the defaultChecked attribute doesn’t update because React doesn’t reapply defaultChecked on updates. The radio buttons maintain their existing state unless explicitly controlled.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search