Core React Native has no radio button component; its user interface list holds only Button and Switch. Build one from Pressable: draw an outer circle and an inner dot, keep the selected value in the parent, and give each option accessibilityRole="radio" plus accessibilityState={{ checked }}. Wrap the set in a View with accessibilityRole="radiogroup".
| Element | Prop | Value |
|---|---|---|
| Wrapping View | accessibilityRole | "radiogroup" |
| Each option | accessibilityRole | "radio" |
| Each option | accessibilityState | { checked: true or false } |
| Disabled option | accessibilityState | { disabled: true }, plus the Pressable disabled prop |
| Newer alternative | role / aria-checked | role="radio" with aria-checked; role wins over accessibilityRole |
Updated
Below is a web version of the same group: it uses the matching ARIA roles, so arrow keys move the choice the way a browser radio set does. Under it, the panel prints the props each option would carry in React Native for the current selection, so you can see what a screen reader is told.
Delivery method
Click an option or use the arrow keys once the group has focus.
Only core components. The parent passes value and onChange, exactly like a controlled TextInput.
import { Pressable, StyleSheet, Text, View } from "react-native";
export function RadioGroup({ label, options, value, onChange }) {
return (
<View accessibilityRole="radiogroup" accessibilityLabel={label}>
<Text style={s.label}>{label}</Text>
{options.map((o) => {
const checked = o.value === value;
return (
<Pressable
key={o.value}
accessibilityRole="radio"
accessibilityState={{ checked, disabled: !!o.disabled }}
disabled={o.disabled}
hitSlop={8}
onPress={() => onChange(o.value)}
style={({ pressed }) => [s.row, pressed && { opacity: 0.6 }]}
>
<View style={s.ring}>{checked ? <View style={s.dot} /> : null}</View>
<Text>{o.label}</Text>
</Pressable>
);
})}
</View>
);
}
const s = StyleSheet.create({
label: { fontWeight: "600", marginBottom: 8 },
row: { flexDirection: "row", alignItems: "center", gap: 10, paddingVertical: 10 },
ring: { width: 22, height: 22, borderRadius: 11, borderWidth: 2, borderColor: "#2563eb", alignItems: "center", justifyContent: "center" },
dot: { width: 10, height: 10, borderRadius: 5, backgroundColor: "#2563eb" },
});State lives in the screen, so the choice can be validated and submitted with the rest of a form.
const [delivery, setDelivery] = useState("standard");
<RadioGroup
label="Delivery method"
value={delivery}
onChange={setDelivery}
options={[
{ value: "standard", label: "Standard shipping" },
{ value: "express", label: "Express shipping" },
{ value: "pickup", label: "Pick up in store", disabled: true },
]}
/>
A radio group is a small amount of code: a row, two circles and a comparison. Writing it yourself means it matches your design, adds nothing to the bundle and carries exactly the accessibility props you choose.
Keeping the selected value in the parent turns the group into a controlled component, so it slots into a form's values object just like a TextInput does.
Use a View with equal width and height, a border and a borderRadius of half the size for the ring. Inside, render a smaller filled View only when the option is selected.
Keep the ring visible in both states and change only the dot. A selection shown by colour alone is hard to see for people with colour blindness.
No. The official components page lists Button and Switch as the only user interface controls, so radios come from your own Pressable code or from a UI kit you install.
Set accessibilityRole="radio" on the Pressable and accessibilityState={{ checked: isSelected }}. The docs describe the radio role as representing a radio button and radiogroup as a group of them.
Either works. React Native also accepts role="radio" and aria-checked, and the docs say role takes precedence over accessibilityRole when both are set. Pick one style and use it across the app.
A Switch is for one on and off setting that takes effect at once. Radios are for picking exactly one of several named options.
Related: React Native dropdown, React Native forms, aria-label examples, React Native collapsible sections, React vs React Native.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.