How to Display a Selected Radio Button Value Elsewhere in React
Advertisement
🧩 Scenario
Architecture Walkthrough
Controlled Radio Groups
A radio input in React is controlled when its checked attribute is computed from React state. Every time the user selects a radio button, the onChange handler updates the state. React re-renders the component, computes the new checked value for each radio, and the DOM reflects the current selection. React state is the single source of truth.
Using defaultChecked makes the input uncontrolled: the DOM tracks the selection internally and React state is not kept in sync. If you later read the state to display the selected value elsewhere, you get stale or incorrect data.
The name Attribute
All radio inputs in a group must share the same name attribute. The browser uses this to ensure only one button in the group can be selected at a time. Without it, each radio button behaves independently and multiple can be checked simultaneously.
Displaying the Value Elsewhere
Once the selected value is in state, displaying it anywhere is straightforward: render the state value in a paragraph, a read-only input, or any other element. A read-only controlled input (value={selected} readOnly) is appropriate when the display should look like an input field but not be editable.
Key Code Explained
interface Option {
value: string;
label: string;
}
const SHIPPING_OPTIONS: Option[] = [
{ value: 'standard', label: 'Standard (5-7 days)' },
{ value: 'express', label: 'Express (2-3 days)' },
{ value: 'overnight', label: 'Overnight (1 day)' },
];
function ShippingSelector() {
// Initialize with the first option selected by default
const [selected, setSelected] = useState<string>(SHIPPING_OPTIONS[0].value);
return (
<div>
<fieldset>
<legend>Select shipping method:</legend>
{SHIPPING_OPTIONS.map((option) => (
<label key={option.value} style={{ display: 'block', marginBottom: 8 }}>
<input
type="radio"
name="shipping" // groups all three radios together
value={option.value}
checked={selected === option.value} // controlled: derived from state
onChange={(e) => setSelected(e.target.value)}
/>
{' '}
{option.label}
</label>
))}
</fieldset>
{/* Display selected value in a read-only input */}
<div style={{ marginTop: 16 }}>
<label>Selected method:</label>
<input
type="text"
value={selected} // controlled read-only display
readOnly
style={{ marginLeft: 8, backgroundColor: '#f5f5f5' }}
/>
</div>
{/* Or display inline */}
<p>You selected: <strong>{selected}</strong></p>
</div>
);
}
// Reusable RadioGroup component
interface RadioGroupProps {
name: string;
options: Option[];
value: string;
onChange: (value: string) => void;
label?: string;
}
function RadioGroup({ name, options, value, onChange, label }: RadioGroupProps) {
return (
<fieldset>
{label && <legend>{label}</legend>}
{options.map((option) => (
<label key={option.value} className="radio-option">
<input
type="radio"
name={name}
value={option.value}
checked={value === option.value}
onChange={(e) => onChange(e.target.value)}
/>
{option.label}
</label>
))}
</fieldset>
);
}
// Usage in a form
function CheckoutForm() {
const [shipping, setShipping] = useState('standard');
const [plan, setPlan] = useState('monthly');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
submitOrder({ shipping, plan });
};
return (
<form onSubmit={handleSubmit}>
<RadioGroup
name="shipping"
options={SHIPPING_OPTIONS}
value={shipping}
onChange={setShipping}
label="Shipping method"
/>
<RadioGroup
name="plan"
options={[{ value: 'monthly', label: 'Monthly' }, { value: 'yearly', label: 'Yearly' }]}
value={plan}
onChange={setPlan}
label="Billing period"
/>
<button type="submit">Place Order</button>
</form>
);
}
Wrapping the radio group in a <fieldset> with a <legend> is important for accessibility. Screen readers announce the legend as the group label before reading each option. Without this structure, a user navigating by keyboard or screen reader has no context for what they are selecting.
Tradeoffs
| Approach | State ownership | Sync with display | Reusable | Use when |
|---|---|---|---|---|
| Controlled (checked) | React state | Always in sync | Yes | Any time selection drives other UI |
| Uncontrolled (defaultChecked) | DOM | Not in sync | No | Unmanaged form with native submit |
What Interviewers Actually Check
- Whether you use
checked(controlled) rather thandefaultChecked(uncontrolled) - Whether you include the
nameattribute for grouping - Whether you derive
checkedfrom state rather than managing it in the DOM - Whether you initialize state with a default selection
- Whether you can extract the radio group into a reusable component
Follow-Up Questions
- How would you integrate a controlled radio group with
react-hook-form'sControllercomponent? - How do you handle a radio group where the options are loaded asynchronously and the initial value is not yet known?
- What is the
aria-checkedattribute and when would you need it for a custom radio button implementation? - How would you test that selecting an option updates the displayed value using React Testing Library?
- How would you reset the radio group to its default selection when a Reset button is clicked?
Common Candidate Mistakes
- Using
defaultCheckedand wondering why the displayed value does not update when a different radio is selected - Omitting the
nameattribute and not understanding why multiple radios can be selected simultaneously - Using array index as the key instead of
option.value, which causes incorrect reconciliation when options are reordered - Not providing an initial state value, leaving the radio group in an unselected state with no
checkedvalue - Not wrapping the group in a
fieldsetandlegend, missing the accessibility requirement
Interview Readiness Checklist
Before you leave this question, make sure you can answer:
- Can you build a controlled radio group where
checkedis derived from state? - Can you display the selected value in a separate read-only input or paragraph?
- Can you explain the difference between
checked(controlled) anddefaultChecked(uncontrolled)? - Can you initialize the radio group with a default selection?
- Can you extract the radio group into a reusable
RadioGroupcomponent?
Summary
A controlled radio group in React uses checked={state === option.value} to derive each radio's checked state from React state. When the user selects an option, onChange updates the state, React re-renders, and all checked values are recomputed. The DOM reflects React state; React state is the single source of truth.
The name attribute groups radio buttons at the HTML level so only one can be selected at a time. All radios in a group must share the same name. Omitting it allows multiple radios to be checked simultaneously.
Displaying the selected value elsewhere is straightforward: render the state variable in any element. A read-only controlled input provides an input-like display without allowing the user to type. Extracting the radio group into a reusable RadioGroup component that accepts name, options, value, and onChange as props is the standard pattern in component libraries.
What makes a radio group controlled in React?
A radio input is controlled when its checked attribute is derived from React state and its onChange handler updates that state. React owns the selected value; the DOM reflects it.
Advertisement
Stay Updated
Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.
Advertisement