Reference version

This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 56).

List

A virtualized vertical container of rows, paired with a tappable ListItem primitive.

Android
iOS
Web
Included in Expo Go

For the complete documentation index, see llms.txt. Use this file to discover all available pages.

List provides a virtualized vertical container of rows, typically populated with ListItem children. It provides the platform-native chrome (separators, inset styling, pull-to-refresh). ListItem is a tappable row with leading/trailing/supportingText slots.

List does not lazily render rows yet: React creates every row up front, so large lists can be slow to mount. We are working on improving this. For large lists, we recommend FlashList or Legend List.

Installation

Terminal
npx expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Basic list

ListExample.tsx
import { useState } from 'react'; import { Host, List, ListItem, Text } from '@expo/ui'; const ITEMS = [ { id: 1, name: 'Avocado toast' }, { id: 2, name: 'Bagel with cream cheese' }, { id: 3, name: 'Cappuccino' }, ]; export default function ListExample() { const [selected, setSelected] = useState<string | null>(null); return ( <Host style={{ flex: 1 }}> <List> {ITEMS.map(item => ( <ListItem key={item.id} onPress={() => setSelected(item.name)}> {item.name} </ListItem> ))} </List> {selected != null && <Text>Selected: {selected}</Text>} </Host> ); }

Rows with slots

ListItem accepts leading, trailing, and supportingText shorthand props for the common case. Pass a ReactNode for any of them when richer content is needed.

ListItemSlotsExample.tsx
import { Host, Icon, List, ListItem } from '@expo/ui'; const CHEVRON = Icon.select({ ios: 'chevron.right', android: require('@expo/material-symbols/chevron_right.xml'), }); export default function ListItemSlotsExample() { return ( <Host style={{ flex: 1 }}> <List> <ListItem onPress={() => {}} trailing={<Icon name={CHEVRON} size={14} color="gray" />} supportingText="Secondary line below the headline"> Profile </ListItem> <ListItem onPress={() => {}} trailing={<Icon name={CHEVRON} size={14} color="gray" />}> Settings </ListItem> </List> </Host> ); }

Compound slot children

For full control over slot content, use the compound API: <ListItem.Leading>, <ListItem.Trailing>, and <ListItem.Supporting>. Anything not wrapped in a slot becomes the headline.

ListItemCompoundExample.tsx
import { Host, Icon, List, ListItem, Row, Text } from '@expo/ui'; export default function ListItemCompoundExample() { return ( <Host style={{ flex: 1 }}> <List> <ListItem onPress={() => {}}> <ListItem.Leading> <Icon name="star.fill" size={20} color="#FFD60A" /> </ListItem.Leading> <Row spacing={0}> <Text textStyle={{ color: 'gray' }}>{`#42: `}</Text> <Text>Composite headline</Text> </Row> <ListItem.Supporting>Richer slot content</ListItem.Supporting> </ListItem> </List> </Host> ); }

Pull-to-refresh

Pass an async onRefresh handler. The platform-native refresh indicator stays visible until the returned promise settles (resolves or rejects).

ListRefreshExample.tsx
import { useState } from 'react'; import { Host, List, ListItem } from '@expo/ui'; export default function ListRefreshExample() { const [items, setItems] = useState([1, 2, 3]); const handleRefresh = async () => { await new Promise(resolve => setTimeout(resolve, 1500)); setItems(prev => [Math.max(...prev) + 1, ...prev]); }; return ( <Host style={{ flex: 1 }}> <List onRefresh={handleRefresh}> {items.map(id => ( <ListItem key={id}>{`Item #${id}`}</ListItem> ))} </List> </Host> ); }

Pull-to-refresh is not implemented on web yet. The handler is accepted for API parity but the indicator only appears on Android and iOS.

API

import { List, ListItem } from '@expo/ui';

Component

List

Android
iOS
Web

Type: React.Element<ListProps>

A vertical container of rows. Typically populated with ListItem children.

Props for the List component. A virtualized vertical container of rows. Typically populated with ListItem children, though any node is accepted.

ListProps

children

Android
iOS
Web
Optional • Type: ReactNode

The list rows. Usually <ListItem> elements.

onRefresh

Android
iOS
Optional • Type: () => Promise<void>

Optional pull-to-refresh handler. When provided, the list shows the platform-native refresh affordance. The returned promise drives the indicator's visibility.

testID

Android
iOS
Web
Optional • Type: string

Identifier used to locate the component in end-to-end tests.

Components

ListItem

Android
iOS
Web

Type: React.Element<ListItemProps>

A tappable row in a list. Composes with List. Pass row content via the leading / trailing / supportingText shorthand props or the compound <ListItem.Leading> / <ListItem.Trailing> / <ListItem.Supporting> slot children.

Props for the ListItem component. A tappable row in a list.

ListItemProps

children

Android
iOS
Web
Optional • Type: ReactNode

Headline content of the row. The remaining (non-slot) children are rendered in the headline area.

leading

Android
iOS
Web
Optional • Type: ReactNode

Shorthand for the leading slot. Overridden by <ListItem.Leading> if both are provided.

onPress

Android
iOS
Web
Optional • Type: () => void

Tap handler. Activates over the entire row rectangle, including the empty gap between leading/headline/trailing.

supportingText

Android
iOS
Web
Optional • Type: ReactNode

Shorthand for the supporting (sub-)text slot. Strings are rendered with platform-appropriate secondary styling; pass a ReactNode for richer content. Overridden by <ListItem.Supporting> if both are provided.

testID

Android
iOS
Web
Optional • Type: string

Identifier used to locate the component in end-to-end tests.

trailing

Android
iOS
Web
Optional • Type: ReactNode

Shorthand for the trailing slot. Overridden by <ListItem.Trailing> if both are provided.

ListItem.Leading

Android
iOS
Web

Type: React.Element<FC<ListItemLeadingProps>>

Props for the ListItem.Leading slot marker.

ListItemLeadingProps

children

Android
iOS
Web
Optional • Type: ReactNode

Content rendered in the leading (start) slot.

ListItem.Supporting

Android
iOS
Web

Type: React.Element<FC<ListItemSupportingProps>>

Props for the ListItem.Supporting slot marker.

ListItemSupportingProps

children

Android
iOS
Web
Optional • Type: ReactNode

Content rendered below the headline.

ListItem.Trailing

Android
iOS
Web

Type: React.Element<FC<ListItemTrailingProps>>

Props for the ListItem.Trailing slot marker.

ListItemTrailingProps

children

Android
iOS
Web
Optional • Type: ReactNode

Content rendered in the trailing (end) slot.