How to use radio buttons in ReactJS?
Emily Wong
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
213 Answers
Any changes to the rendering should be change via the state or props (react doc).
So here I register the event of the input, and then change the state, which will then trigger the render to show on the footer.
var SearchResult = React.createClass({ getInitialState: function () { return { site: '', address: '', }; }, onSiteChanged: function (e) { this.setState({ site: e.currentTarget.value, }); }, onAddressChanged: function (e) { this.setState({ address: e.currentTarget.value, }); }, render: function () { var resultRows = this.props.data.map(function (result) { return ( <tbody> <tr> <td> <input type="radio" name="site_name" value={result.SITE_NAME} checked={this.state.site === result.SITE_NAME} onChange={this.onSiteChanged} /> {result.SITE_NAME} </td> <td> <input type="radio" name="address" value={result.ADDRESS} checked={this.state.address === result.ADDRESS} onChange={this.onAddressChanged} /> {result.ADDRESS} </td> </tr> </tbody> ); }, this); return ( <table className="table"> <thead> <tr> <th>Name</th> <th>Address</th> </tr> </thead> {resultRows} <tfoot> <tr> <td>chosen site name {this.state.site} </td> <td>chosen address {this.state.address} </td> </tr> </tfoot> </table> ); },
}); 4 Here is the simplest way of implementing radio buttons in react js.
class App extends React.Component { setGender(event) { console.log(event.target.value); } render() { return ( <div onChange={this.setGender.bind(this)}> <input type="radio" value="MALE" name="gender"/> Male <input type="radio" value="FEMALE" name="gender"/> Female </div> ) }
}
ReactDOM.render(<App/>, document.getElementById('app'));<script src=""></script>
<script src=""></script>
<div></div>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 13 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 value="windows" name="platform" type="radio" onChange={this.handleChange} /> Mac <input value="mac" name="platform" type="radio" onChange={this.handleChange} /> Linux <input value="linux" name="platform" type="radio" onChange={this.handleChange} /> </div> ); }
}Link to example:
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:
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;It's easy to test as it is a dumb component (a pure function).
2Just 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:
import React from "react"
import ReactDOM from "react-dom"
// This Component should obviously be a class if you want it to work ;)
const RadioInputs = (props) => { /* [[Label, associated value], ...] */ const inputs = [["Male", "M"], ["Female", "F"], ["Other", "O"]] return ( <div> { inputs.map(([text, value], i) => ( <div key={ i }> <input type="radio" checked={ this.state.gender === value } onChange={ /* You'll need an event function here */ } value={ value } /> { text } </div> )) } </div> )
}
ReactDOM.render( <RadioInputs />, document.getElementById("root")
)<script src=""></script>
<script src=""></script>
<div></div> 4 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; 2 Here's what I have used. Hope this helps.
Defining variable first.
const [variableName, setVariableName] = useState("");Then, we will need the actual radio buttons.
<input type="radio" name="variableName" value="variableToCheck" onChange={(e) => setVariableName("variableToCheck") } checked={variableName === "variableToCheck"}
/> Clicking a radio button should trigger an event that either:
- calls setState, if you only want the selection knowledge to be local, or
- 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.
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.
/* * A simple React component */
class App extends React.Component { constructor(params) { super(params) // initial gender state set from props this.state = { gender: this.props.gender } this.setGender = this.setGender.bind(this) } setGender(e) { this.setState({ gender: e.target.value }) } render() { const {gender} = this.state return <div> Gender: <div> <input type="radio" checked={gender == "male"}
onClick={this.setGender} value="male" /> Male <input type="radio" checked={gender == "female"}
onClick={this.setGender} value="female" /> Female </div> { "Select Gender: " } {gender} </div>; }
}
/* * Render the above component into the div#app */
ReactDOM.render(<App gender="male" />, document.getElementById('app'));<script src=""></script>
<script src=""></script>
<div></div> 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.
@Tomasz Mularczyk mentions react hooks in his answer, but I thought I'd put in a solution I recently used that uses just the useState hook.
function Radio() { const [currentRadioValue, setCurrentRadioValue] = useState() const handleRadioChange = (e) => { setCurrentValue(e.target.value); }; return ( <> <div> <input name="radio-item-1" type="radio" value="radio-1" onChange={handleRadioChange} checked={currentRadioValue === 'radio-1'} /> <label htmlFor="radio-item-1">Radio Item 1</label> </div> <div> <input name="radio-item-2" type="radio" value="radio-2" onChange={handleRadioChange} checked={currentRadioValue === 'radio-2'} /> <label htmlFor="radio-item-2"> Radio Item 1 </label> </div> </> );
} 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> </> )
} import React from 'react';
import './style.css';
export default function App() { const [currentRadioValue, setCurrentValue] = React.useState('on'); const handleRadioChange = value => { setCurrentValue(value); }; return ( <div> <> <div> <input name="radio-item-1" value="on" type="radio" onChange={e => setCurrentValue(e.target.value)} defaultChecked={currentRadioValue === 'on'} /> <label htmlFor="radio-item-1">Radio Item 1</label> {currentRadioValue === 'on' && <div>one</div>} </div> <div> <input name="radio-item-1" value="off" type="radio" onChange={e => setCurrentValue(e.target.value)} defaultChecked={currentRadioValue === 'off'} /> <label htmlFor="radio-item-2">Radio Item 2</label> {currentRadioValue === 'off' && <div>two</div>} </div> </> </div> );
}working example:
1