0
# Scene Mapping
1
2
Scene mapping provides utility functions for efficiently mapping route keys to React components and creating scene renderers. The SceneMap function is the most common way to define tab content in React Native Tab View.
3
4
## Capabilities
5
6
### SceneMap Function
7
8
Helper function that creates scene renderers from a mapping of route keys to React components.
9
10
```typescript { .api }
11
/**
12
* Creates a scene renderer function from a component mapping
13
* @param scenes - Object mapping route keys to React components
14
* @returns Scene renderer function compatible with TabView.renderScene
15
*/
16
function SceneMap<T>(scenes: { [key: string]: React.ComponentType<T> }):
17
(props: SceneRendererProps & { route: Route }) => React.ReactElement;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import React from 'react';
24
import { View, Text } from 'react-native';
25
import { TabView, SceneMap } from 'react-native-tab-view';
26
27
// Define individual scene components
28
const HomeScreen = () => (
29
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
30
<Text>Home Screen</Text>
31
</View>
32
);
33
34
const ProfileScreen = () => (
35
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
36
<Text>Profile Screen</Text>
37
</View>
38
);
39
40
const SettingsScreen = () => (
41
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
42
<Text>Settings Screen</Text>
43
</View>
44
);
45
46
// Create scene renderer using SceneMap
47
const renderScene = SceneMap({
48
home: HomeScreen,
49
profile: ProfileScreen,
50
settings: SettingsScreen,
51
});
52
53
// Use with TabView
54
const TabViewExample = () => {
55
const [index, setIndex] = useState(0);
56
const [routes] = useState([
57
{ key: 'home', title: 'Home' },
58
{ key: 'profile', title: 'Profile' },
59
{ key: 'settings', title: 'Settings' },
60
]);
61
62
return (
63
<TabView
64
navigationState={{ index, routes }}
65
renderScene={renderScene}
66
onIndexChange={setIndex}
67
/>
68
);
69
};
70
```
71
72
### Advanced Scene Rendering
73
74
For more complex scenarios, you can create custom scene renderers instead of using SceneMap.
75
76
```typescript { .api }
77
/**
78
* Custom scene renderer function type
79
* @param props - Scene renderer props including route and navigation context
80
* @returns React node to render for the scene
81
*/
82
type SceneRenderer<T extends Route> = (
83
props: SceneRendererProps & { route: T }
84
) => React.ReactNode;
85
86
/**
87
* Scene renderer props interface
88
*/
89
interface SceneRendererProps {
90
/** Current layout dimensions */
91
layout: Layout;
92
/** Animated position value for transitions */
93
position: Animated.AnimatedInterpolation<number>;
94
/** Function to navigate to a specific route */
95
jumpTo: (key: string) => void;
96
}
97
```
98
99
**Custom Scene Renderer Examples:**
100
101
```typescript
102
import React from 'react';
103
import { TabView, NavigationState, Route } from 'react-native-tab-view';
104
105
// Custom scene renderer with conditional logic
106
const renderScene = ({ route, layout, position, jumpTo }: SceneRendererProps & { route: Route }) => {
107
switch (route.key) {
108
case 'home':
109
return <HomeScreen layout={layout} position={position} jumpTo={jumpTo} />;
110
case 'profile':
111
return <ProfileScreen userId={getCurrentUserId()} />;
112
case 'settings':
113
return <SettingsScreen onNavigate={jumpTo} />;
114
case 'notifications':
115
return (
116
<NotificationsScreen
117
badgeCount={getNotificationCount()}
118
onMarkAllRead={() => markAllNotificationsRead()}
119
/>
120
);
121
default:
122
return null;
123
}
124
};
125
126
// Scene renderer with props passing
127
const renderSceneWithProps = (sceneProps: SceneRendererProps & { route: Route }) => {
128
const commonProps = {
129
theme: currentTheme,
130
user: currentUser,
131
navigation: sceneProps.jumpTo,
132
};
133
134
switch (sceneProps.route.key) {
135
case 'feed':
136
return <FeedScreen {...commonProps} refreshing={isRefreshing} />;
137
case 'search':
138
return <SearchScreen {...commonProps} query={searchQuery} />;
139
case 'profile':
140
return <ProfileScreen {...commonProps} userId={sceneProps.route.userId} />;
141
default:
142
return null;
143
}
144
};
145
```
146
147
### Scene Component Architecture
148
149
Understanding how SceneMap creates scene components internally.
150
151
```typescript { .api }
152
/**
153
* Internal scene component props
154
*/
155
interface SceneProps {
156
/** Route object */
157
route: any;
158
/** Function to navigate to route */
159
jumpTo: (key: string) => void;
160
/** Animated position value */
161
position: Animated.AnimatedInterpolation<number>;
162
}
163
164
/**
165
* Internal SceneComponent for rendering individual scenes
166
*/
167
declare const SceneComponent: React.MemoExoticComponent<
168
<T extends { component: React.ComponentType<any> } & SceneProps>(
169
props: T
170
) => React.ReactElement
171
>;
172
```
173
174
### Performance Considerations
175
176
SceneMap uses React.memo for performance optimization and efficient re-rendering.
177
178
**Performance Best Practices:**
179
180
```typescript
181
// ✅ Good: Components defined outside render
182
const HomeScreen = React.memo(() => (
183
<View><Text>Home</Text></View>
184
));
185
186
const ProfileScreen = React.memo(() => (
187
<View><Text>Profile</Text></View>
188
));
189
190
const renderScene = SceneMap({
191
home: HomeScreen,
192
profile: ProfileScreen,
193
});
194
195
// ❌ Avoid: Inline components (will recreate on every render)
196
const renderScene = SceneMap({
197
home: () => <View><Text>Home</Text></View>,
198
profile: () => <View><Text>Profile</Text></View>,
199
});
200
201
// ✅ Better: Memoized inline components if necessary
202
const renderScene = SceneMap({
203
home: React.memo(() => <View><Text>Home</Text></View>),
204
profile: React.memo(() => <View><Text>Profile</Text></View>),
205
});
206
```
207
208
### Dynamic Scene Loading
209
210
Handling dynamic route configurations and lazy-loaded scenes.
211
212
```typescript
213
// Dynamic scene mapping based on user permissions
214
const createSceneMap = (userRoles: string[]) => {
215
const scenes: { [key: string]: React.ComponentType } = {
216
home: HomeScreen,
217
profile: ProfileScreen,
218
};
219
220
if (userRoles.includes('admin')) {
221
scenes.admin = AdminScreen;
222
scenes.analytics = AnalyticsScreen;
223
}
224
225
if (userRoles.includes('moderator')) {
226
scenes.moderation = ModerationScreen;
227
}
228
229
return SceneMap(scenes);
230
};
231
232
// Lazy loading with dynamic imports
233
const LazySceneMap = (scenes: { [key: string]: () => Promise<{ default: React.ComponentType }> }) => {
234
const [loadedScenes, setLoadedScenes] = useState<{ [key: string]: React.ComponentType }>({});
235
236
const renderScene = ({ route }: { route: Route }) => {
237
const SceneComponent = loadedScenes[route.key];
238
239
if (SceneComponent) {
240
return <SceneComponent />;
241
}
242
243
// Load scene dynamically
244
const loader = scenes[route.key];
245
if (loader) {
246
loader().then(module => {
247
setLoadedScenes(prev => ({
248
...prev,
249
[route.key]: module.default,
250
}));
251
});
252
}
253
254
return <LoadingPlaceholder />;
255
};
256
257
return renderScene;
258
};
259
260
// Usage with dynamic imports
261
const lazyRenderScene = LazySceneMap({
262
home: () => import('./screens/HomeScreen'),
263
profile: () => import('./screens/ProfileScreen'),
264
settings: () => import('./screens/SettingsScreen'),
265
});
266
```
267
268
### Integration with Navigation Libraries
269
270
SceneMap works seamlessly with React Navigation and other navigation libraries.
271
272
```typescript
273
// Integration with React Navigation
274
import { useNavigation } from '@react-navigation/native';
275
276
const NavigationAwareScreen = () => {
277
const navigation = useNavigation();
278
279
return (
280
<View>
281
<Button
282
title="Go to Details"
283
onPress={() => navigation.navigate('Details')}
284
/>
285
</View>
286
);
287
};
288
289
const renderScene = SceneMap({
290
tabs: NavigationAwareScreen,
291
});
292
293
// Passing navigation props through scene renderer
294
const renderSceneWithNavigation = ({ route, jumpTo }: SceneRendererProps & { route: Route }) => {
295
const navigationProps = {
296
jumpTo,
297
canGoBack: () => true,
298
goBack: () => jumpTo('home'),
299
};
300
301
switch (route.key) {
302
case 'home':
303
return <HomeScreen navigation={navigationProps} />;
304
case 'profile':
305
return <ProfileScreen navigation={navigationProps} />;
306
default:
307
return null;
308
}
309
};
310
```