ShipNative
PricingBlogFAQContact
Build my app
ShipNative
PricingBlogFAQContact
Build my app
GuideOctober 2026 · 7 min read · By Saurabh Singh

React Native Radio Button: Build One That Works

React Native has a Switch but no radio button. That surprises people, and it leads to two common mistakes: installing a heavy UI kit for one plan picker, or building a group where each option keeps its own boolean and two can end up selected. This guide shows the 40-line component most apps should write, the state model that makes impossible selections impossible, the accessibility props screen readers need, and when a library is the better call.

Your three options

OptionInstallExpo GoBest for
Build with PressableNothingYesCustom look, one or two groups, full control
React Native Paper RadioButtonreact-native-paperYesApps already using Paper / Material Design
react-native-radio-buttons-groupSmall JS packageYesQuick prototypes with default styling

All three are plain JavaScript on top of core components, so none needs a development build. If your app already uses React Native Paper, use its RadioButton.Groupand stop reading. Otherwise, building it yourself is less code than learning a library's styling API, and you get a control that looks like the rest of your app.

One value for the group, not one boolean per option

The defining rule of a radio group is that exactly one option is selected. Model that directly: the group owns one value, and each option is selected when its value equals it.

// Fragile: nothing stops two of these being true
const [monthly, setMonthly] = useState(true);
const [yearly, setYearly] = useState(false);

// Robust: one value, impossible to select two
type Plan = 'monthly' | 'yearly';
const [plan, setPlan] = useState<Plan>('yearly');

The single value is also what you save to your database or send to your payment screen, so there is no translation step. A union type like Plan means TypeScript catches a typo in an option value before it ships.

The component: accessible radio group in about 40 lines

import { Pressable, StyleSheet, Text, View } from 'react-native';

type Option<T extends string> = { value: T; label: string; hint?: string };

export function RadioGroup<T extends string>({
  label,
  options,
  value,
  onChange,
}: {
  label: string;
  options: Option<T>[];
  value: T;
  onChange: (next: T) => void;
}) {
  return (
    <View accessibilityRole="radiogroup" accessibilityLabel={label}>
      {options.map((opt) => {
        const checked = opt.value === value;
        return (
          <Pressable
            key={opt.value}
            onPress={() => onChange(opt.value)}
            accessibilityRole="radio"
            accessibilityState={{ checked }}
            accessibilityLabel={opt.label}
            accessibilityHint={opt.hint}
            style={styles.row}
          >
            <View style={[styles.circle, checked && styles.circleOn]}>
              {checked ? <View style={styles.dot} /> : null}
            </View>
            <View style={{ flex: 1 }}>
              <Text style={styles.label}>{opt.label}</Text>
              {opt.hint ? <Text style={styles.hint}>{opt.hint}</Text> : null}
            </View>
          </Pressable>
        );
      })}
    </View>
  );
}

const styles = StyleSheet.create({
  row: { flexDirection: 'row', alignItems: 'center', minHeight: 48, paddingVertical: 10, gap: 12 },
  circle: { width: 22, height: 22, borderRadius: 11, borderWidth: 2, borderColor: '#6b6b6b',
    alignItems: 'center', justifyContent: 'center' },
  circleOn: { borderColor: '#fb923c' },
  dot: { width: 10, height: 10, borderRadius: 5, backgroundColor: '#fb923c' },
  label: { fontSize: 16, color: '#fff' },
  hint: { fontSize: 13, color: '#8a8a8a', marginTop: 2 },
});

Using it:

const [plan, setPlan] = useState<'monthly' | 'yearly'>('yearly');

<RadioGroup
  label="Billing period"
  value={plan}
  onChange={setPlan}
  options={[
    { value: 'monthly', label: 'Monthly', hint: '$6 per month' },
    { value: 'yearly', label: 'Yearly', hint: '$48 per year, save 33%' },
  ]}
/>

Three details do the work. The whole row is the Pressable, so tapping the label selects the option and the touch target is 48 points tall instead of a 22-point circle. The radio role plus checkedstate makes VoiceOver and TalkBack announce “Yearly, radio button, selected, 2 of 2”. And the group label tells a screen-reader user what question the options answer.

Variations people usually need next

  • Card-style options. For plan pickers, replace the row style with a bordered card and highlight the border when checked. The logic does not change.
  • Nothing selected yet. If the user must make an active choice, type the value as T | null, start at null, and disable the Continue button until it is set. Do not preselect an option you want people to think about.
  • Inside a form.Treat the group like any other field: the value goes into your form state and validation reports “Choose a delivery speed” under the group. The form validation guide covers the error display pattern.
  • Horizontal layout. Set the container to flexDirection: 'row' for two short options like Yes / No. Past three options, go back to vertical, because labels wrap badly on small phones.

Radio, checkbox, switch, or dropdown?

Radio buttons are for one choice from a small set the user should compare. Several choices at once is a checkbox list. A single on/off that takes effect immediately is a switch. A long list such as countries or time zones is a dropdown, because ten radio rows push the rest of the form off screen.

If you would rather describe the screen than write it, “a checkout screen with a radio group for standard, express, and next-day delivery, prices on the right”, ShipNative generates the accessible group and the state wiring as real React Native, and runs it on your phone so you can check it with VoiceOver before you ship.

Frequently Asked Questions

Does React Native have a built-in radio button?

No. React Native core ships Switch but no radio button or checkbox. You either build one from Pressable and View, which takes about 40 lines, or use a library such as React Native Paper, which includes RadioButton, or react-native-radio-buttons-group.

How do I store which radio button is selected?

Store one value for the whole group, such as the id of the selected option, not a boolean per option. One value makes it impossible to have two options selected at once, and it maps directly to what you save: plan = "yearly", not yearly = true and monthly = false.

How do I make radio buttons accessible in React Native?

Give the container accessibilityRole="radiogroup" and an accessibilityLabel that names the question. Give each option accessibilityRole="radio" and accessibilityState={{ checked }}. Make the whole row pressable, not only the circle, so the touch target is at least 44 points tall.

Should I use a radio group or a dropdown?

Use radio buttons for two to about five options the user should compare at a glance, such as shipping speed or plan length. Use a dropdown or a picker when there are many options, such as country, or when the options are self-explanatory and screen space matters.

Can I style the radio button to match my brand?

Yes, and that is the main reason to build your own. The circle is a View with a border radius and a border; the dot is a smaller View inside it. Change the colours, size, or swap the circle for a card-style option without fighting a library API.

Can an AI app builder generate a radio group?

Yes. Describe the choice, "a plan picker with monthly and yearly options, yearly preselected and showing the saving", and ShipNative generates the accessible radio group and wires it to state as real React Native you can run on your phone.

→

React Native Checkbox

For choices where several options can be selected at once.

Read guide →
→

React Native Dropdown & Select

The better control when you have more than five options.

Read guide →

Ship a real React Native app today

Describe, preview, and export Expo code, free to start.

Build with ShipNative
ShipNative

Build mobile apps with AI. Describe it, try it on your phone, own the code.

Features

Text to App AIApp Generator from ScreenshotPRD to Mobile App

Tools

All free toolsApp Cost CalculatorApp Name GeneratorApp Store Keyword ToolReact Native Components

Blog

All blog postsHow to Build an App Without CodingBest AI Tools for Real Mobile AppsExpo EAS App Store ChecklistLovable, Cursor & v0 for MobileBest AI App Builders in 2026React Native AI App Builder Guide
© 2026 ShipNative
PrivacyTermsAboutFAQPricingDiscordShipNative - Featured on Startup FameFeatured on Twelve ToolsFeatured on TinyShelfShipNative - Launched on Fazier