skip to Main Content

I am trying to create a Raidobutton in React. Below is the code.
When I click on first radio button("Windows") , the Radiobutton shows checked, when I click second one ("Mac") the Radiobutton does not show checked even though the checked is true. When we again click on "Mac" Radiobutton gets checked.And after that all Radiobutton works fine.
Can somebody help with this.

import './App.css';
import { useState } from 'react';

const options = ["Windows", "Mac", "Linux"]
const days = ["Male", "Female"]

const TempRadio = ({ item, group }) => {

  const [checked, setChecked] = useState('')
  const handleChnage = (e) => {
    console.log(e.target.value)
    setChecked(() => e.target.value)
  }
  return (
    <label>
      <input type="radio" value={item} checked={item === checked} name={group} onChange={ handleChnage} />{item}
    </label>

  )
}
function App() {


  const renderItems = (items, group) => {
    return <div className='myul'>{items.map((item) =>
      <TempRadio item={item} key={item} group={group} />

    )}</div>

  }
  return (
    <div className="App">
      <header className="App-header">
        <h1>
          Which OS?
        </h1>
        {renderItems(options, "OS")}
        <h2>Gender</h2>
        {renderItems(days, "time")}
      </header>
    </div>
  );
}

export default App;

2

Answers


  1. You are creating radio buttons the wrong way. Beacuse you give each one it’s own state it will not work:

    What you need is something like this:

    import './App.css';
    import { useState } from 'react';
    
    function App() {
      const [checked, setChecked] = useState('');
    
      const options = ['Windows', 'Mac', 'Linux'];
      const days = ['Male', 'Female'];
    
      const handleChnage = (e) => {
        console.log(e.target.value);
        setChecked(() => e.target.value);
      };
    
      console.log(checked);
    
      const renderItems = (items, group) => {
        return (
          <div className="myul">
            {items.map((item) => (
              <label>
                <input
                  type="radio"
                  value={item}
                  checked={item === checked}
                  name={group}
                  onChange={handleChnage}
                />
                {item}
              </label>
            ))}
          </div>
        );
      };
    
      return (
        <div className="App">
          <header className="App-header">
            <h1>Which OS?</h1>
            {renderItems(options, 'OS')}
            <h2>Gender</h2>
            {renderItems(days, 'time')}
          </header>
        </div>
      );
    }
    
    export default App;
    
    
    Login or Signup to reply.
  2. Since you’re grouping radio buttons, and you’ll probably want to do "something" with the output from both sets, it makes sense to shift the responsibility of state management to the parent component (in this case App).

    So in app the state is an object that uses the group value as a key, and the value of the clicked radio button as its value.

    In this example I’ve create a RadioGroup component to help manage the flow of data. The respective options get passed down here, as well as the group label, the group name, the state for that group, and the shared handler.

    (The useEffect is temporary – it just shows how the state is updated when the buttons are changed within each radio group. I also relabelled your days/time variable as it didn’t seem to relate to the actual content – gender.)

    const { useEffect, useState, Fragment } = React;
    
    function App({ os, gender }) {
    
      // Initialise the state as an object with
      // OS and gender properties
      const [ radios, setRadios ] = useState({ os: '', gender: '' });
      
      // The value of the clicked radio, and its group, are
      // passed to the handler (which is itself passed to the
      // component). The value of the group in the state object
      // is updated
      function handleUpdate(value, group) {
        setRadios(prev => {
          return { ...prev, [group]: value };
        });
      }
    
      // An effect to show how state changes
      useEffect(() => console.log(radios), [radios]);
    
      // Add the RadioGroup components, passing down the state for
      // the group, and the handler
      return (
        <main className="App">
          <RadioGroup
            options={os}
            group="os"
            label="OS"
            checked={radios.os}
            handleUpdate={handleUpdate}
          />
          <RadioGroup
            options={gender}
            group="gender"
            label="Gender"
            checked={radios.gender}
            handleUpdate={handleUpdate}
          />
        </main>
      );
    }
    
    function RadioGroup(props) {
    
      const {
        options,
        group,
        label,
        handleUpdate,
        checked
      } = props;
    
      // When a radio button is clicked we extract the value, and
      // name from it (relabelling `name` as `group` for
      // consistency, and then call the handler with those values
      function handleChange(e) {
        if (e.target.matches('input[type="radio"]')) {
          const { value, name: group } = e.target;
          handleUpdate(value, group);
        }
      }
    
      // For convenience we add the change listener to the
      // the radio button section so it can catch events from
      // its children as they bubble up the DOM
      return (
        <section class="radiogroup" onChange={handleChange}>
          <h1>{label}</h1>
          {options.map(option => {
            return (
              <Fragment>
                <label>{option}</label>
                <input
                  type="radio"
                  checked={option === checked}
                  value={option}
                  name={group}
                />
              </Fragment>
            );
          })}
        </section>
      );
    
    }
    
    const os = ['Windows', 'Mac', 'Linux'];
    const gender = ['Male', 'Female'];
    
    ReactDOM.render(
      <App os={os} gender={gender} />,
      document.getElementById('react')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <div id="react"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search