DEV Community

Cover image for Multiple Radio Buttons in React
Greg
Greg

Posted on • Updated on

Multiple Radio Buttons in React

Demo
repo

We have all been there staring at the same five or more radio buttons with same value or worse no value.

All we want is each radio button to have their own state value. The confusion lies at the heart of the DOM value vs the DOM element

Intro

I am going to code five radio buttons and show the underpinnings of react and how to handle multiple buttons in a single piece of state

Short version:

  • The value of an element is a primitive data type:boolean, number etc
  • The element is the actual node like html tag, className, id etc
  • Event handler will make the connection to the state

Getting started

npx create-react-app radio-buttons See the screenshot for the folder structure and code. I cleaned up the boilerplate and added useState go here for the repo.

React scaffold

App.js



const App = () => {
  return (
    <div className='App'>
      <h1>Radio Journey</h1>
    </div>
  );
};

export default App;



Enter fullscreen mode Exit fullscreen mode

Index.js



import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);



Enter fullscreen mode Exit fullscreen mode

Index.css

Style for style points on your own or see mine later in the demo Styles

Ok now that we have the basic set up lets code through it.

We need to add state and a radio button such as



import { useState } from 'react';

const App = () => {
  //STATE
  const [isRadio, setIsRadio] = useState(5);

  return (
    <div className='App'>
      <h1>Radio Journey</h1>
      <ul>
        <li>
          <input />
          <label>1</label>
        </li>
      </ul>
    </div>
  );
};

export default App;


Enter fullscreen mode Exit fullscreen mode

Next the <input/> and <label/> need a few props like so



import { useState } from 'react';

const App = () => {

//STATE
  const [isRadio, setIsRadio] = useState(5);


  return (
    <div className='App'>
      <h1>Radio Journey</h1>
      <ul>
        <li>
          <input
            type='radio'
            id='radio1'
            value='1'
            onChange={handleChange}
            checked={isRadio === 1}
          />
          <label htmlFor='num1'>1</label>
        </li>
      </ul>
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

Styles

add style to get a visual interface of whats going on. Add this to your index.css



* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Courier New', Courier, monospace;
  background-color: #090c57cb;
  color: #fff;
  line-height: 1.8;
}

ul {
  list-style: none;
}
h1 {
  text-align: center;
}
.container {
  max-width: 768px;
  margin: auto;
  padding: 0 20px;
}

input {
  flex-grow: 2;
  border: none;
  font-size: 16px;
}

input:focus {
  outline: none;
}

.radios {
  display: flex;
  align-items: center;
  justify-content: space-around;
  margin: 30px 0 40px;
}

.radios li {
  position: relative;
  background: #f4f4f4;
  width: 50px;
  height: 50px;
  padding: 10px;
  text-align: center;
  border-radius: 50%;
  font-size: 19px;
  border: 1px #eee solid;
  transition: 0.3s;
}
li label {
  position: absolute;
  top: 110%;
  left: 0;
  width: 50px;
  height: 50px;
  padding: 10px;
  border-radius: 50%;
}

.radios li:hover {
  background: #f00303;
  color: #fff;
}

[type='radio'] {
  opacity: 0;
}

[type='radio']:checked ~ label {
  background: #f00303;
  color: #fff;
}


Enter fullscreen mode Exit fullscreen mode

Should look like this

UI

The <input/> has everything it needs and we have styles. Next address the handleChange and add four more radio buttons.



import { useState } from 'react';

const App = () => {
  //STATE
  const [isRadio, setIsRadio] = useState(5);

  // HANDLE THE ONCHANGE HERE

  const handleChange = (e) => {
    // string passed in
    // a string returned by default
    console.log(e.currentTarget.value);
    // add + to the event to make the value a number
    setIsRadio(+e.currentTarget.value);
  };

  return (
    <div className='App'>
      <h1>Radio Journey</h1>
      <ul className='radios'>
        <li>
          <input
            type='radio'
            id='radio1'
            value='1'
            onChange={handleChange}
            checked={isRadio === 1}
          />
          <label htmlFor='num1'>1</label>
        </li>
        <li>
          <input
            type='radio'
            id='radio2'
            value='2'
            onChange={handleChange}
            checked={isRadio === 2}
          />
          <label htmlFor='num2'>2</label>
        </li>
        <li>
          <input
            type='radio'
            id='radio3'
            value='3'
            onChange={handleChange}
            checked={isRadio === 3}
          />
          <label htmlFor='num3'>3</label>
        </li>
        <li>
          <input
            type='radio'
            id='radio4'
            value='4'
            onChange={handleChange}
            checked={isRadio === 4}
          />
          <label htmlFor='num4'>4</label>
        </li>
        <li>
          <input
            type='radio'
            id='radio5'
            value='5'
            onChange={handleChange}
            checked={isRadio === 5}
          />
          <label htmlFor='num5'>5</label>
        </li>
      </ul>


Enter fullscreen mode Exit fullscreen mode

You should have this in your browser:

5 Radios

Notice the console.log(e.currentTarget.value)

Here is definition of the currentTarget Docs here:
"The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM."

Let's run back through it. We have five radio buttons each one has a string value captured by the handleChange function when clicked. The string value needs to be changed to a number by adding the '+' sign in front of the e like so setIsRadio(+e.currentTarget.value);

Now that the clicked value is a number it gets updated to the state and isRadio is a new value. The checked prop is a unique identifier for the state to match to 'Hey checked your number value matches let's make you the star of the show'.

click event > handleChange > updates state > checked made it to the show.

Like always confirm with dev tools:
Dev tools

Conclusion
In this demo my intent was to show how to effectively utilize one piece of state with hooks and multiple radio buttons in code. The console and dev tools confirmed the UI is matching the state changes. I hope this demo was helpful. This demo is could easily be used to create your next radio button component and be further optimized.

  • There are a few ways to handle multiple radio buttons especially as they get nested into components which is out of the scope of this demo.

Links 🔗

useState
Input
Checked
currentTarget

❤️❤️❤️

Social

Twitter
Linkedin
Portfolio
Github

🤘
Thank you for reading happy coding!

Github Repo

GitHub logo GregPetropoulos / Radio-Buttons-Demo

A demo on several radio buttons. I created five radio buttons and show the underpinnings of react and how to handle multiple buttons in a single piece of state

Top comments (0)