Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: How to determine if a collection of radio buttons have a selected item?

Given the following unordered HTML/JSX list:

<ul className="settings">
  <li>
    <input type="radio" name="settings" id="beginner" ref={selectedSetting} onClick={handleSettingsChange}/>
    <label htmlFor="beginner">Beginner</label>
  </li>
  <li>
    <input type="radio" name="settings" id="intermediate" ref={selectedSetting} onClick={handleSettingsChange}/>
    <label htmlFor="intermediate">Intermediate</label>
  </li>
  <li>
    <input type="radio" name="settings" id="expert" ref={selectedSetting} onClick={handleSettingsChange}/>
    <label htmlFor="expert">Expert</label>
  </li>
  <li>
    <input type="radio" name="settings" id="custom" ref={selectedSetting} onClick={handleSettingsChange}/>
    <label htmlFor="custom">Custom</label>
  </li>
</ul>

with a submit button that fires the following function:

const onSubmit = (e: MouseEvent): void => {
  console.log(selectedSetting.current)
}

I want to validate that at least one of these radio buttons have been selected. As you can see I was using a single useRef variable here which would cause the "custom" radio button to be logged every time. The straight forward solution, then, is to have a useRef for each radio button but is there an easier way to do this? Can I instead give the ul tag a ref and do something similar to jQuery to see if one of them has been selected?

like image 547
aarona Avatar asked Oct 23 '25 07:10

aarona


1 Answers

You can handle the onClick event for the radio buttons in order to set state to the currently selected radio.

Something like this:

const { useRef, useState } = React;
const { render } = ReactDOM;

function App() {
    const [selected, setSelected] = useState();
    const selectedSetting = useRef();
  
    const handleSettingsChange = e => setSelected(e.target.id);
  
    const handleSubmit = () => {
      selected 
        ? alert("Selected radio: " + selected) 
        : alert("Nothing Selected!");
    }
    
    return(
      <div>
        <ul className="settings">
          <li>
            <input type="radio" name="settings" id="beginner" ref={selectedSetting} onClick={handleSettingsChange}/>
            <label htmlFor="beginner">Beginner</label>
          </li>
          <li>
            <input type="radio" name="settings" id="intermediate" ref={selectedSetting} onClick={handleSettingsChange}/>
            <label htmlFor="intermediate">Intermediate</label>
          </li>
          <li>
            <input type="radio" name="settings" id="expert" ref={selectedSetting} onClick={handleSettingsChange}/>
            <label htmlFor="expert">Expert</label>
          </li>
          <li>
            <input type="radio" name="settings" id="custom" ref={selectedSetting} onClick={handleSettingsChange}/>
            <label htmlFor="custom">Custom</label>
          </li>
        </ul>
        <div>
          <button onClick={handleSubmit}>Submit</button>
        </div>
      </div>
    );
}

render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>

UPDATED ANSWER:

This would be a much cleaner, more "React" way to accomplish this...

const { useState } = React;
const { render } = ReactDOM;

const MY_RADIOS = ["Beginner", "Intermediate", "Expert", "Custom"];

function App({radios}) {
    const [selected, setSelected] = useState();
  
    const handleClick = radio => event => setSelected(radio);
  
    const handleSubmit = () => {
      let msg = selected 
        ? "Selected radio: " + selected
        : "Nothing Selected!";
      alert(msg);
    }
    
    return(
      <div>
        <ul className="settings">
          {radios && radios.map(r => {
            return (
              <li>
                <label>
                  <input onClick={handleClick(r)} type="radio" name="settings" />
                  {r}
                </label>
              </li>
            )
          })}
        </ul>
        <div>
          <button onClick={handleSubmit}>Submit</button>
        </div>
      </div>
    );
}

render(<App radios={MY_RADIOS} />, document.body);
li {
  list-style-type: none;  
}

ul {
  padding-left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
like image 194
Matt Oestreich Avatar answered Oct 25 '25 21:10

Matt Oestreich



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!