Quick Start
This guide demonstrates how to set up expo-split-view in an Expo Router application.
Flexible Route Structure
expo-split-view works in any Expo Router route group — inside a tab layout, as a standalone stack, or nested within a drawer. A tab layout is not required but is fully supported. Common scenarios include:
- A tab inside
app/(tabs)/items/— split view as one tab among others - A standalone stack at
app/items/— no tabs at all - Nested inside a drawer at
app/(drawer)/items/
File Structure
A standard file structure for a split-view route group looks like this:
app/
items/
_layout.tsx <-- Layout coordinator (<SplitView>)
index.tsx <-- Root index screen (<SplitView.Placeholder>)
[id]/
index.tsx <-- Detail screen (<SplitView.Detail>)
components/
MasterList.tsx <-- Shared master list with useSplitView()Step-by-Step Implementation
1. Route Group Layout (app/items/_layout.tsx)
Render <SplitView> in your route group layout, passing your master list component:
import React from 'react';
import { MasterList } from '@/components/MasterList';
import { SplitView } from 'expo-split-view';
export default function ItemsLayout() {
return <SplitView masterList={<MasterList />} />;
}2. Route Index (app/items/index.tsx)
Use <SplitView.Placeholder> for the root index screen. On mobile, it displays the master list full-screen. On tablet, it displays a placeholder until an item is selected:
import React from 'react';
import { MasterList } from '@/components/MasterList';
import { SplitView } from 'expo-split-view';
export default function ItemsIndex() {
return (
<SplitView.Placeholder
masterList={<MasterList />}
placeholderText="Select an item from the list to view its details."
/>
);
}3. Master List Component (components/MasterList.tsx)
Use the useSplitView hook to handle navigation. Calling navigate(route) automatically calls router.replace on tablets and router.push on mobile devices:
import React from 'react';
import { FlatList, Text, TouchableOpacity } from 'react-native';
import { useSplitView } from 'expo-split-view';
export function MasterList({ items }: { items: { id: string; title: string }[] }) {
const { navigate, isTablet } = useSplitView();
return (
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => navigate(`/items/${item.id}`)}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
);
}4. Detail Screen (app/items/[id]/index.tsx)
Wrap your detail screen in <SplitView.Detail> to automatically attach edge-swipe gesture handlers, and call useDetailScreenBack to handle back button behavior:
import React from 'react';
import { Text, View } from 'react-native';
import { useLocalSearchParams } from 'expo-router';
import { SplitView, useDetailScreenBack } from 'expo-split-view';
export default function ItemDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
useDetailScreenBack({
title: `Item #${id}`,
fallbackRoute: '/items',
});
return (
<SplitView.Detail>
<View>
<Text>Viewing details for item #{id}</Text>
</View>
</SplitView.Detail>
);
}Next Steps
- Check out Customization to tailor placeholder content, back options, and header icons.
- Explore the Example App to see a full, interactive implementation with filters, search, and nested navigation.
