How to use radio buttons in ReactJS?
HtmlReactjsHtml Problem Overview
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
Html Solutions
Solution 1 - Html
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>
);
},
});
Solution 2 - Html
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="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></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
Solution 3 - Html
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
Solution 4 - Html
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).
Solution 5 - Html
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:
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="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Solution 6 - Html
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;
Solution 7 - Html
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"}
/>
Solution 8 - Html
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.
Solution 9 - Html
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="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Solution 10 - Html
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.
Solution 11 - Html
@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
id="radio-item-1"
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
id="radio-item-2"
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>
</>
);
}
Solution 12 - Html
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>
</>
)
}
Solution 13 - Html
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: https://stackblitz.com/edit/react-ovnv2b