[html] How to use radio buttons in ReactJS?

I am new to ReactJS, sorry if this sounds off. I have a component that creates several table rows according to the received data.

Each cell within the column has a radio checkbox. Hence the user can select one site_name and one address from the existing rows. The selection shall be shown in the footer. And thats where I am stuck.

var SearchResult = React.createClass({
   render: function(){
       var resultRows = this.props.data.map(function(result){
           return (
               <tbody>
                    <tr>
                        <td><input type="radio" name="site_name" value={result.SITE_NAME}>{result.SITE_NAME}</input></td>
                        <td><input type="radio" name="address" value={result.ADDRESS}>{result.ADDRESS}</input></td>
                    </tr>
               </tbody>
           );
       });
       return (
           <table className="table">
               <thead>
                   <tr>
                       <th>Name</th>
                       <th>Address</th>
                   </tr>
               </thead>
                {resultRows}
               <tfoot>
                   <tr>
                       <td>chosen site name ???? </td>
                       <td>chosen address ????? </td>
                   </tr>
               </tfoot>
           </table>
       );
   }
});

In jQuery I could do something like $("input[name=site_name]:checked").val() to get the selection of one radio checkbox type and insert it into the first footer cell.

But surely there must be a Reactjs way, which I am totally missing? Many Thanks

This question is related to html reactjs

The answer is


Clicking a radio button should trigger an event that either:

  1. calls setState, if you only want the selection knowledge to be local, or
  2. calls a callback that has been passed in from above self.props.selectionChanged(...)

In the first case, the change is state will trigger a re-render and you can do
<td>chosen site name {this.state.chosenSiteName} </td>

in the second case, the source of the callback will update things to ensure that down the line, your SearchResult instance will have chosenSiteName and chosenAddress set in it's props.


Based on what React Docs say:

Handling Multiple Inputs. When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.

For example:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  handleChange = e => {
    const { name, value } = e.target;

    this.setState({
      [name]: value
    });
  };

  render() {
    return (
      <div className="radio-buttons">
        Windows
        <input
          id="windows"
          value="windows"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Mac
        <input
          id="mac"
          value="mac"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Linux
        <input
          id="linux"
          value="linux"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

Link to example: https://codesandbox.io/s/6l6v9p0qkr

At first, none of the radio buttons is selected so this.state is an empty object, but whenever the radio button is selected this.state gets a new property with the name of the input and its value. It eases then to check whether user selected any radio-button like:

const isSelected = this.state.platform ? true : false;

EDIT:

With version 16.7-alpha of React there is a proposal for something called hooks which will let you do this kind of stuff easier:

In the example below there are two groups of radio-buttons in a functional component. Still, they have controlled inputs:

function App() {
  const [platformValue, plaftormInputProps] = useRadioButtons("platform");
  const [genderValue, genderInputProps] = useRadioButtons("gender");
  return (
    <div>
      <form>
        <fieldset>
          Windows
          <input
            value="windows"
            checked={platformValue === "windows"}
            {...plaftormInputProps}
          />
          Mac
          <input
            value="mac"
            checked={platformValue === "mac"}
            {...plaftormInputProps}
          />
          Linux
          <input
            value="linux"
            checked={platformValue === "linux"}
            {...plaftormInputProps}
          />
        </fieldset>
        <fieldset>
          Male
          <input
            value="male"
            checked={genderValue === "male"}
            {...genderInputProps}
          />
          Female
          <input
            value="female"
            checked={genderValue === "female"}
            {...genderInputProps}
          />
        </fieldset>
      </form>
    </div>
  );
}

function useRadioButtons(name) {
  const [value, setState] = useState(null);

  const handleChange = e => {
    setState(e.target.value);
  };

  const inputProps = {
    name,
    type: "radio",
    onChange: handleChange
  };

  return [value, inputProps];
}

Working example: https://codesandbox.io/s/6l6v9p0qkr


Just an idea here: when it comes to radio inputs in React, I usually render all of them in a different way that was mentionned in the previous answers.

If this could help anyone who needs to render plenty of radio buttons:

_x000D_
_x000D_
import React from "react"_x000D_
import ReactDOM from "react-dom"_x000D_
_x000D_
// This Component should obviously be a class if you want it to work ;)_x000D_
_x000D_
const RadioInputs = (props) => {_x000D_
  /*_x000D_
    [[Label, associated value], ...]_x000D_
  */_x000D_
  _x000D_
  const inputs = [["Male", "M"], ["Female", "F"], ["Other", "O"]]_x000D_
  _x000D_
  return (_x000D_
    <div>_x000D_
      {_x000D_
        inputs.map(([text, value], i) => (_x000D_
   <div key={ i }>_x000D_
     <input type="radio"_x000D_
              checked={ this.state.gender === value } _x000D_
       onChange={ /* You'll need an event function here */ } _x000D_
       value={ value } /> _x000D_
         { text }_x000D_
          </div>_x000D_
        ))_x000D_
      }_x000D_
    </div>_x000D_
  )_x000D_
}_x000D_
_x000D_
ReactDOM.render(_x000D_
  <RadioInputs />,_x000D_
  document.getElementById("root")_x000D_
)
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>_x000D_
_x000D_
<div id="root"></div>
_x000D_
_x000D_
_x000D_


To build upon ChinKang said for his answer, I have a more dry'er approach and in es6 for those interested:

class RadioExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      selectedRadio: 'public'
    };
  }

  handleRadioChange = (event) => {
    this.setState({
      selectedRadio: event.currentTarget.value
    })
  };

  render() {
    return (
      <div className="radio-row">
        <div className="input-row">
          <input
            type="radio"
            name="public"
            value="public"
            checked={this.state.selectedRadio === 'public'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="public">Public</label>
        </div>
        <div className="input-row">
          <input
            type="radio"
            name="private"
            value="private"
            checked={this.state.selectedRadio === 'private'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="private">Private</label>
        </div>
      </div>
    )
  }
}

except this one would have a default checked value.


I also got confused in radio, checkbox implementation. What we need is, listen change event of the radio, and then set the state. I have made small example of gender selection.

_x000D_
_x000D_
/*_x000D_
 * A simple React component_x000D_
 */_x000D_
class App extends React.Component {_x000D_
  constructor(params) {_x000D_
     super(params) _x000D_
     // initial gender state set from props_x000D_
     this.state = {_x000D_
       gender: this.props.gender_x000D_
     }_x000D_
     this.setGender = this.setGender.bind(this)_x000D_
  }_x000D_
  _x000D_
  setGender(e) {_x000D_
    this.setState({_x000D_
      gender: e.target.value_x000D_
    })_x000D_
  }_x000D_
  _x000D_
  render() {_x000D_
    const {gender} = this.state_x000D_
    return  <div>_x000D_
        Gender:_x000D_
        <div>_x000D_
          <input type="radio" checked={gender == "male"} _x000D_
onClick={this.setGender} value="male" /> Male_x000D_
          <input type="radio" checked={gender == "female"} _x000D_
onClick={this.setGender} value="female"  /> Female_x000D_
        </div>_x000D_
        { "Select Gender: " } {gender}_x000D_
      </div>;_x000D_
  }_x000D_
}_x000D_
_x000D_
/*_x000D_
 * Render the above component into the div#app_x000D_
 */_x000D_
ReactDOM.render(<App gender="male" />, document.getElementById('app'));
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>_x000D_
<div id="app"></div>
_x000D_
_x000D_
_x000D_


Here is a simplest way of implementing radio buttons in react js.

_x000D_
_x000D_
class App extends React.Component {_x000D_
  _x000D_
  setGender(event) {_x000D_
    console.log(event.target.value);_x000D_
  }_x000D_
  _x000D_
  render() {_x000D_
    return ( _x000D_
      <div onChange={this.setGender.bind(this)}>_x000D_
        <input type="radio" value="MALE" name="gender"/> Male_x000D_
        <input type="radio" value="FEMALE" name="gender"/> Female_x000D_
      </div>_x000D_
     )_x000D_
  }_x000D_
}_x000D_
_x000D_
ReactDOM.render(<App/>, document.getElementById('app'));
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>_x000D_
<div id="app"></div>
_x000D_
_x000D_
_x000D_

Edited

You can use arrow function instead of binding. Replace the above code as

<div onChange={event => this.setGender(event)}>

For a default value use defaultChecked, like this

<input type="radio" value="MALE" defaultChecked name="gender"/> Male

Bootstrap guys, we do it like this:


export default function RadioButton({ onChange, option }) {
    const handleChange = event => {
        onChange(event.target.value)
    }

    return (
        <>
            <div className="custom-control custom-radio">
                <input
                    type="radio"
                    id={ option.option }
                    name="customRadio"
                    className="custom-control-input"
                    onChange={ handleChange }
                    value = { option.id }
                    />
                    <label
                        className="custom-control-label"
                        htmlFor={ option.option }
                        >
                        { option.option }
                    </label>
            </div>
        </>
    )
}


Make the radio component as dumb component and pass props to from parent.

import React from "react";

const Radiocomponent = ({ value, setGender }) => ( 
  <div onChange={setGender.bind(this)}>
    <input type="radio" value="MALE" name="gender" defaultChecked={value ==="MALE"} /> Male
    <input type="radio" value="FEMALE" name="gender" defaultChecked={value ==="FEMALE"}/> Female
  </div>
);

export default Radiocomponent;

import React, { Component } from "react";

class RadionButtons extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // gender : "" , // use this one if you don't wanna any default value for gender
      gender: "male" // we are using this state to store the value of the radio button and also use to display the active radio button
    };

    this.handleRadioChange = this.handleRadioChange.bind(this);  // we require access to the state of component so we have to bind our function 
  }

  // this function is called whenever you change the radion button 
  handleRadioChange(event) {
      // set the new value of checked radion button to state using setState function which is async funtion
    this.setState({
      gender: event.target.value
    });
  }


  render() {
    return (
      <div>
        <div check>
          <input
            type="radio"
            value="male" // this is te value which will be picked up after radio button change
            checked={this.state.gender === "male"} // when this is true it show the male radio button in checked 
            onChange={this.handleRadioChange} // whenever it changes from checked to uncheck or via-versa it goes to the handleRadioChange function
          />
          <span
           style={{ marginLeft: "5px" }} // inline style in reactjs 
          >Male</span>
        </div>
        <div check>
          <input
            type="radio"
            value="female"
            checked={this.state.gender === "female"}
            onChange={this.handleRadioChange}
          />
          <span style={{ marginLeft: "5px" }}>Female</span>
        </div>
      </div>
    );
  }
}
export default RadionButtons;

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release