Skip to content

Commit 1832930

Browse files
Migrate 'Navigation events' examples to static API in v7 (#1330)
* Add static examples * Remvoe dependencies, default and use useNavigation instead of prop * Navigation events cleanup --------- Co-authored-by: kacperkapusciak <kacper.kapusciak@swmansion.com>
1 parent d6a0529 commit 1832930

2 files changed

Lines changed: 239 additions & 7 deletions

File tree

versioned_docs/version-7.x/navigating-without-navigation-prop.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,10 @@ function Settings({ route }) {
128128
}
129129

130130
const RootStack = createNativeStackNavigator({
131-
Home: Home,
132-
Settings: Settings,
131+
screens: {
132+
Home: Home,
133+
Settings: Settings,
134+
},
133135
});
134136

135137
const Navigation = createStaticNavigation(RootStack);

versioned_docs/version-7.x/navigation-events.md

Lines changed: 235 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ title: Navigation events
44
sidebar_label: Navigation events
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
You can listen to various events emitted by React Navigation to get notified of certain events, and in some cases, override the default action. There are few core events such as `focus`, `blur` etc. (documented below) that work for every navigator, as well as navigator specific events that work only for certain navigators.
811

912
Apart from the core events, each navigator can emit their own custom events. For example, stack navigator emits `transitionStart` and `transitionEnd` events, tab navigator emits `tabPress` event etc. You can find details about the events emitted on the individual navigator's documentation.
@@ -55,24 +58,146 @@ const unsubscribe = navigation.addListener('tabPress', (e) => {
5558

5659
Normally, you'd add an event listener in `React.useEffect` for function components. For example:
5760

58-
<samp id="simple-focus-and-blur" />
61+
<Tabs groupId="config" queryString="config">
62+
<TabItem value="static" label="Static" default>
5963

60-
```js
61-
function Profile() {
64+
```js name="navigation.addListener with focus" snack version=7
65+
import * as React from 'react';
66+
import { View, Text } from 'react-native';
67+
import { Button } from '@react-navigation/elements';
68+
import {
69+
createStaticNavigation,
70+
useNavigation,
71+
} from '@react-navigation/native';
72+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
73+
74+
function SettingsScreen() {
75+
const navigation = useNavigation();
76+
77+
return (
78+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
79+
<Text>Settings Screen</Text>
80+
<Button onPress={() => navigation.navigate('Profile')}>
81+
Go to Profile
82+
</Button>
83+
</View>
84+
);
85+
}
86+
87+
// codeblock-focus-start
88+
function ProfileScreen() {
6289
const navigation = useNavigation();
6390

6491
React.useEffect(() => {
6592
const unsubscribe = navigation.addListener('focus', () => {
66-
// do something
93+
// Screen was focused
6794
});
95+
return unsubscribe;
96+
}, [navigation]);
6897

98+
React.useEffect(() => {
99+
const unsubscribe = navigation.addListener('blur', () => {
100+
// Screen was unfocused
101+
});
69102
return unsubscribe;
70103
}, [navigation]);
71104

72-
return <ProfileContent />;
105+
// Rest of the component
106+
// codeblock-focus-end
107+
return (
108+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
109+
<Text>Profile Screen</Text>
110+
<Button onPress={() => navigation.navigate('Settings')}>
111+
Go to Settings
112+
</Button>
113+
</View>
114+
);
115+
// codeblock-focus-start
116+
}
117+
// codeblock-focus-end
118+
119+
const SettingsStack = createNativeStackNavigator({
120+
screens: {
121+
Settings: SettingsScreen,
122+
Profile: ProfileScreen,
123+
},
124+
});
125+
126+
const Navigation = createStaticNavigation(SettingsStack);
127+
128+
export default function App() {
129+
return <Navigation />;
73130
}
74131
```
75132

133+
</TabItem>
134+
<TabItem value="dynamic" label="Dynamic">
135+
136+
```js name="navigation.addListener with focus" snack version=7
137+
import * as React from 'react';
138+
import { View, Text } from 'react-native';
139+
import { Button } from '@react-navigation/elements';
140+
import { NavigationContainer, useNavigation } from '@react-navigation/native';
141+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
142+
143+
function SettingsScreen({ navigation }) {
144+
return (
145+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
146+
<Text>Settings Screen</Text>
147+
<Button onPress={() => navigation.navigate('Profile')}>
148+
Go to Profile
149+
</Button>
150+
</View>
151+
);
152+
}
153+
154+
// codeblock-focus-start
155+
function ProfileScreen({ navigation }) {
156+
React.useEffect(() => {
157+
const unsubscribe = navigation.addListener('focus', () => {
158+
// Screen was focused
159+
});
160+
return unsubscribe;
161+
}, [navigation]);
162+
163+
React.useEffect(() => {
164+
const unsubscribe = navigation.addListener('blur', () => {
165+
// Screen was unfocused
166+
});
167+
return unsubscribe;
168+
}, [navigation]);
169+
170+
// Rest of the component
171+
// codeblock-focus-end
172+
return (
173+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
174+
<Text>Profile Screen</Text>
175+
<Button onPress={() => navigation.navigate('Settings')}>
176+
Go to Settings
177+
</Button>
178+
</View>
179+
);
180+
// codeblock-focus-start
181+
}
182+
// codeblock-focus-end
183+
184+
const SettingsStack = createNativeStackNavigator();
185+
186+
export default function App() {
187+
return (
188+
<NavigationContainer>
189+
<SettingsStack.Navigator>
190+
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
191+
<SettingsStack.Screen name="Profile" component={ProfileScreen} />
192+
</SettingsStack.Navigator>
193+
</NavigationContainer>
194+
);
195+
}
196+
```
197+
198+
</TabItem>
199+
</Tabs>
200+
76201
The `unsubscribe` function can be returned as the cleanup function in the effect.
77202

78203
For class components, you can add the event in the `componentDidMount` lifecycle method and unsubscribe in `componentWillUnmount`:
@@ -113,6 +238,28 @@ Sometimes you might want to add a listener from the component where you defined
113238

114239
Example:
115240

241+
<Tabs groupId="config" queryString="config">
242+
<TabItem value="static" label="Static" default>
243+
244+
```js
245+
const Tab = createBottomTabNavigatior({
246+
screens: {
247+
Chat: {
248+
screen: Chat,
249+
listeners: {
250+
tabPress: (e) => {
251+
// Prevent default action
252+
e.preventDefault;
253+
},
254+
},
255+
},
256+
},
257+
});
258+
```
259+
260+
</TabItem>
261+
<TabItem value="dynamic" label="Dynamic">
262+
116263
```js
117264
<Tab.Screen
118265
name="Chat"
@@ -126,9 +273,36 @@ Example:
126273
/>
127274
```
128275

276+
</TabItem>
277+
</Tabs>
278+
129279
You can also pass a callback which returns the object with listeners. It'll receive `navigation` and `route` as the arguments.
130280

131281
Example:
282+
<Tabs groupId="config" queryString="config">
283+
<TabItem value="static" label="Static" default>
284+
285+
```js
286+
const Tab = createBottomTabNavigatior({
287+
screens: {
288+
Chat: {
289+
screen: Chat,
290+
listeners: ({ navigation, route }) => ({
291+
tabPress: (e) => {
292+
// Prevent default action
293+
e.preventDefault;
294+
295+
// Do something with the `navigation` object
296+
navigation.navigate('AnotherPlace');
297+
},
298+
}),
299+
},
300+
},
301+
});
302+
```
303+
304+
</TabItem>
305+
<TabItem value="dynamic" label="Dynamic">
132306

133307
```js
134308
<Tab.Screen
@@ -146,12 +320,36 @@ Example:
146320
/>
147321
```
148322

323+
</TabItem>
324+
</Tabs>
325+
149326
### `screenListeners` prop on the navigator
150327

151328
You can pass a prop named `screenListeners` to the navigator component, where you can specify listeners for events from all screens for this navigator. This can be useful if you want to listen to specific events regardless of the screen, or want to listen to common events such as `state` which is emitted to all screens.
152329

153330
Example:
154331

332+
<Tabs groupId="config" queryString="config">
333+
<TabItem value="static" label="Static" default>
334+
335+
```js
336+
const Stack = createNativeStackNavigator({
337+
screenListeners: {
338+
state: (e) => {
339+
// Do something with the state
340+
console.log('state changed', e.data);
341+
},
342+
},
343+
screens: {
344+
Home: HomeScreen,
345+
Profile: ProfileScreen,
346+
},
347+
});
348+
```
349+
350+
</TabItem>
351+
<TabItem value="dynamic" label="Dynamic">
352+
155353
```js
156354
<Stack.Navigator
157355
screenListeners={{
@@ -166,8 +364,37 @@ Example:
166364
</Stack.Navigator>
167365
```
168366

367+
</TabItem>
368+
</Tabs>
369+
169370
Similar to `listeners`, you can also pass a function to `screenListeners`. The function will receive the [`navigation` object](navigation-object.md) and the [`route` object](route-object.md) for each screen. This can be useful if you need access to the `navigation` object.
170371

372+
<Tabs groupId="config" queryString="config">
373+
<TabItem value="static" label="Static" default>
374+
375+
```js
376+
const Tab = createBottomTabNavigatior({
377+
screenListeners: ({ navigation }) => ({
378+
state: (e) => {
379+
// Do something with the state
380+
console.log('state changed', e.data);
381+
382+
// Do something with the `navigation` object
383+
if (!navigation.canGoBack()) {
384+
console.log("we're on the initial screen");
385+
}
386+
},
387+
}),
388+
screens: {
389+
Home: HomeScreen,
390+
Profile: ProfileScreen,
391+
},
392+
});
393+
```
394+
395+
</TabItem>
396+
<TabItem value="dynamic" label="Dynamic">
397+
171398
```js
172399
<Tab.Navigator
173400
screenListeners={({ navigation }) => ({
@@ -186,3 +413,6 @@ Similar to `listeners`, you can also pass a function to `screenListeners`. The f
186413
<Tab.Screen name="Profile" component={ProfileScreen} />
187414
</Tab.Navigator>
188415
```
416+
417+
</TabItem>
418+
</Tabs>

0 commit comments

Comments
 (0)