In React Native, what does accessible={true} on a View do to the elements inside it for VoiceOver and TalkBack?
answer
- one focus stop, not five
- children stop being separate elements
- iOS composes a label from child text
- touchables are accessible by default
- grouped buttons become unreachable
basics
~20 sIt turns the View into a single accessibility element, so the screen reader focuses the group once and reads its children together instead of stopping on each child; Pressable and the other touchables are already accessible by default.
solid answer
~50 s`accessible={true}` makes a `View` one accessibility element: VoiceOver and TalkBack land on the whole group in one swipe, and its children are no longer separate focus stops. On iOS it maps to the native accessibility-element flag, and when the group has no `accessibilityLabel`, React Native builds one from its children's text; on Android it maps to native `focusable`, and TalkBack reads the group's content together. `Pressable` and the other touchables are accessible by default, a plain `View` is not. In an email list I group each row, so sender, subject and time are one stop instead of four. The trap is grouping something that contains its own controls: a Star button inside a grouped row can no longer be reached on its own, so it must move out of the group or become a custom action.
code
tsx · 22 linesimport {Pressable, Text, View} from 'react-native';
type Email = {id: string; sender: string; subject: string; time: string};
export function MailboxHeader({unread}: {unread: number}) {
return (
<View accessible>
<Text>Inbox</Text>
<Text>{unread} unread</Text>
</View>
);
}
export function EmailRow({email, onOpen}: {email: Email; onOpen: (id: string) => void}) {
return (
<Pressable onPress={() => onOpen(email.id)}>
<Text>{email.sender}</Text>
<Text>{email.subject}</Text>
<Text>{email.time}</Text>
</Pressable>
);
}go deeper
Recall that accessible={true} turns a View into one focus stop, and that Pressable and the touchables are accessible without setting it.
Explain how grouping maps to each platform, how iOS composes a label from children, and why a nested button inside a group becomes unreachable.
Show how you decide what to group on a dense screen, when to write an explicit label, and how you confirm the swipe count with VoiceOver and TalkBack.
Discuss setting grouping conventions in shared list and card components so every feature team ships rows that read as one element with the same shape.
## What the prop does In React Native, `accessible` is a prop on `View` (and on everything built on it) that marks the view as an **accessibility element**: one thing a screen reader can land on. **VoiceOver** (iOS) and **TalkBack** (Android) move through a screen one element at a time, usually with a one-finger swipe. By default a plain `View` is not an element; it is a container, and the reader visits the elements inside it one by one. When you set `accessible={true}` on a `View`: - The view becomes **one focus stop**. A single swipe lands on the whole group. - Its descendants **stop being separate stops**. The reader treats them as content of the group rather than things to visit. - On **iOS**, `accessible` becomes the native accessibility-element flag. If the group has no `accessibilityLabel`, React Native builds a label by joining the text of its children, so the group still says something. - On **Android**, `accessible` becomes native `focusable`, and TalkBack speaks the content of the focused group. The React Native docs add a caution worth quoting in an interview: `accessible` makes a view **discoverable**, but it does not guarantee that VoiceOver or TalkBack will focus that exact view, because VoiceOver does not allow nested accessibility elements and TalkBack may choose to focus a parent instead. ## What is accessible by default | Component | Accessible by default? | |---|---| | `Pressable` | yes (unless `accessible={false}`) | | `TouchableOpacity` and the other touchables | yes | | `Text` | on iOS, yes; on Android, only with `onPress` or `onLongPress` (TalkBack still reads plain text) | | `View` | no, it is a container until you set `accessible` | That default is why a tappable email row built with `Pressable` already behaves as one stop: the `Text` children inside it are read as the row's content. ## Why grouping helps Without grouping, an email row with a sender, a subject, a snippet and a time costs four swipes, and the user has to remember which subject belonged to which sender. With the row grouped: 1. One swipe per email. 2. The whole row is read in one utterance: sender, subject, snippet, time. 3. Double-tapping activates the row as a unit, which matches what a sighted user does. Grouping is also the right tool for non-interactive clusters that only make sense together, such as a mailbox header reading "Inbox, 3 unread", where the count alone would be meaningless. ## When grouping hurts - **Controls inside the group disappear.** A Star or Archive button nested inside a grouped row is no longer a separate element, so a screen-reader user cannot reach it. Move the control out of the group, or expose its operation as a custom action on the row with `accessibilityActions`. - **Long groups become walls of speech.** Grouping a whole card with ten fields forces the user to listen to everything to find one value. - **The composed label can be clumsy.** The label React Native builds on iOS follows the children's order and includes every text, decorative ones too. When the row needs a specific phrasing such as "Unread. From Ana. Invoice for March. 9:41", write an explicit label on the group. ## A practical rule Group what a sighted user perceives as **one thing with one action**, and keep separate anything that has **its own action**. For an email list that means: each row is one element, the row's open action is its double-tap, and its secondary operations are either real buttons outside the group or custom actions on it. Check the result by swiping through the list with VoiceOver and with TalkBack; the number of swipes per row and what each swipe says are the test.
- A grouped email row contains a Star button. How do you keep starring available to screen-reader users?Either move the Star button outside the grouped element so it is its own focus stop, or keep the row grouped and expose starring through `accessibilityActions` with an `onAccessibilityAction` handler, so VoiceOver and TalkBack users pick it from the row's actions. Leaving the button nested inside the group makes it unreachable.
- Why can a grouped row read awkwardly on iOS even though every child has text?When the group has no `accessibilityLabel`, React Native on iOS joins its children's text in view order, including decorative text and whatever order the tree happens to have. For a row that needs specific phrasing, such as an unread marker first, set an explicit label on the group.
saying these in an interview costs you the question
- accessible={true} on a View makes each child focusable one by one.
- A Pressable needs accessible={true} before a screen reader can focus it.
- Grouping a row that contains buttons keeps each button separately reachable.
- accessible={true} guarantees VoiceOver and TalkBack focus exactly that view.
- A plain View is an accessibility element by default.