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
Clicking a radio button should trigger an event that either:
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:
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_
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_
* 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_
Here is a simplest way of implementing radio buttons in react js.
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_
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;
Source: Stackoverflow.com