Last Updated: October 18, 2023
My project source code is available here
Overview¶
In React, we can create a radio group component dynamically using the React.Children.map() function. This will allow us to create a radio group component that can be used to render a list of radio buttons.
Rendering the RadioGroup component dynamically allows us to create a reusable component that can be used to render a list of radio buttons. Below is an example of rendering radio buttons manually, which is not reusable. Review the App.jsx file in the Files section below for a complete example.
function App() {
const [selected, setSelected] = useState("");
const handleChange = (e) => e.target.value === selected
return (
<div className="App">
<h2>How did you hear about Little Lemon?</h2>
<RadioGroup onChange={setSelected} selected={selected}>
<RadioOption value="social_media" checked={false} onChange={handleChange}>Social Media</RadioOption>
<RadioOption value="friends" checked={false} onChange={handleChange}>Friends</RadioOption>
<RadioOption value="advertising" checked={false} onChange={handleChange}>Advertising</RadioOption>
<RadioOption value="other" checked={false} onChange={handleChange}>Other</RadioOption>
</RadioGroup>
<button disabled={!selected}>Submit</button>
</div>
);
}Files¶
App.jsx¶
App.jsx¶
import "./App.css";
import { RadioGroup, RadioOption } from "./Radio";
import { useState } from "react";
/**
* App displays a radio group built using component composition dynamically.
* */
function App() {
const [selected, setSelected] = useState("");
// console.log("selected:", selected);
return (
<div className="App">
<h2>How did you hear about Little Lemon?</h2>
<RadioGroup onChange={setSelected} selected={selected}>
<RadioOption value="social_media">Social Media</RadioOption>
<RadioOption value="friends">Friends</RadioOption>
<RadioOption value="advertising">Advertising</RadioOption>
<RadioOption value="other">Other</RadioOption>
</RadioGroup>
<button disabled={!selected}>Submit</button>
</div>
);
}
export default App;
Radio/index.jsx¶
Radio/index.jsx¶
import * as React from "react";
import "./styles.css";
export const RadioGroup = ({ onChange, selected, children }) => {
// Use React.Children.map and React.cloneElement to clone the children
// and pass the correct props to each RadioOption
const RadioOptions = React.Children.map(children, (child) => {
return React.cloneElement(child, {
...child.props,
onChange: onChange,
checked: child.props.value === selected,
});
});
return <div className="RadioGroup">{RadioOptions}</div>;
};
export const RadioOption = ({ value, checked, onChange, children }) => {
// Hook up the onChange handler to call the onChange prop passed to RadioGroup
// Also, make sure to pass the correct checked prop to the input element
return (
<div className="RadioOption">
<input
id={value}
type="radio"
name={value}
value={value}
checked={checked}
onChange={(e) => {
onChange(e.target.value);
}}
/>
<label htmlFor={value}>{children}</label>
</div>
);
};