Skip to content

Commit 46177ee

Browse files
DaniAkashR Nabors
andauthored
πŸ”™ Updated BackHandler Docs with snack examples πŸ€ΎπŸ½β€β™‚οΈ (#1685)
* added snack for BackHandler * fix for the linting issue https://circleci.com/gh/facebook/react-native-website/10092?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link * Updating copy and headers * fix componentWillUnmount in back handler * Example for backhandler.removeeventlistener Co-authored-by: R Nabors <[email protected]>
1 parent f4eea17 commit 46177ee

File tree

1 file changed

+238
-22
lines changed

1 file changed

+238
-22
lines changed

β€Ždocs/backhandler.mdβ€Ž

Lines changed: 238 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,279 @@ id: backhandler
33
title: BackHandler
44
---
55

6-
Detect hardware button presses for back navigation.
6+
The Backhandler API detects hardware button presses for back navigation, lets you register event listeners for the system's back action, and lets you control how your application responds. It is Android-only.
77

8-
Android: Detect hardware back button presses, and programmatically invoke the default back button functionality to exit the app if there are no listeners or if none of the listeners return true.
8+
The event subscriptions are called in reverse order (i.e. the last registered subscription is called first).
99

10-
tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented: programmatically disable menu button handling functionality to exit the app if there are no listeners or if none of the listeners return true.)
10+
- **If one subscription returns true,** then subscriptions registered earlier will not be called.
11+
- **If no subscription returns true or none are registered,** it programmatically invokes the default back button functionality to exit the app.
1112

12-
iOS: Not applicable.
13+
> **Warning for modal users:** If your app shows an opened `Modal`, `BackHandler` will not publish any events ([see `Modal` docs](modal#onrequestclose)).
1314
14-
The event subscriptions are called in reverse order (i.e. last registered subscription first), and if one subscription returns true then subscriptions registered earlier will not be called. Beware: If your app shows an opened `Modal`, BackHandler will not publish any events ([see `Modal` docs](modal#onrequestclose)).
15-
16-
Example:
15+
## Pattern
1716

1817
```jsx
1918
BackHandler.addEventListener('hardwareBackPress', function() {
20-
// this.onMainScreen and this.goBack are just examples, you need to use your own implementation here
21-
// Typically you would use the navigator here to go to the last state.
19+
/**
20+
* this.onMainScreen and this.goBack are just examples,
21+
* you need to use your own implementation here.
22+
*
23+
* Typically you would use the navigator here to go to the last state.
24+
*/
2225

2326
if (!this.onMainScreen()) {
2427
this.goBack();
28+
/**
29+
* When true is returned the event will not be bubbled up
30+
* & no other back action will execute
31+
*/
2532
return true;
2633
}
34+
/**
35+
* Returning false will let the event to bubble up & let other event listeners
36+
* or the system's default back action to be executed.
37+
*/
2738
return false;
2839
});
2940
```
3041

31-
Lifecycle example:
42+
## Example
43+
44+
The following example implements a scenario where you confirm if the user wants to exit the app:
45+
46+
<div class="toggler">
47+
<ul role="tablist" class="toggle-syntax">
48+
<li id="functional" class="button-functional" aria-selected="false" role="tab" tabindex="0" aria-controls="functionaltab" onclick="displayTabs('syntax', 'functional')">
49+
Function Component Example
50+
</li>
51+
<li id="classical" class="button-classical" aria-selected="false" role="tab" tabindex="0" aria-controls="classicaltab" onclick="displayTabs('syntax', 'classical')">
52+
Class Component Example
53+
</li>
54+
</ul>
55+
</div>
56+
57+
<block class="functional syntax" />
58+
59+
```SnackPlayer name=BackHandler&supportedPlatforms=android
60+
import React, { useEffect } from "react";
61+
import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
62+
63+
export default function App() {
64+
useEffect(() => {
65+
const backAction = () => {
66+
Alert.alert("Hold on!", "Are you sure you want to go back?", [
67+
{
68+
text: "Cancel",
69+
onPress: () => null,
70+
style: "cancel"
71+
},
72+
{ text: "YES", onPress: () => BackHandler.exitApp() }
73+
]);
74+
return true;
75+
};
76+
77+
const backHandler = BackHandler.addEventListener(
78+
"hardwareBackPress",
79+
backAction
80+
);
81+
82+
return () => backHandler.remove();
83+
}, []);
84+
85+
return (
86+
<View style={styles.container}>
87+
<Text style={styles.text}>Click Back button!</Text>
88+
</View>
89+
);
90+
}
91+
92+
const styles = StyleSheet.create({
93+
container: {
94+
flex: 1,
95+
alignItems: "center",
96+
justifyContent: "center"
97+
},
98+
text: {
99+
fontSize: 18,
100+
fontWeight: "bold"
101+
}
102+
});
103+
```
104+
105+
<block class="classical syntax" />
106+
107+
```SnackPlayer name=BackHandler&supportedPlatforms=android
108+
import React, { Component } from "react";
109+
import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
110+
111+
export default class App extends Component {
112+
backAction = () => {
113+
Alert.alert("Hold on!", "Are you sure you want to go back?", [
114+
{
115+
text: "Cancel",
116+
onPress: () => null,
117+
style: "cancel"
118+
},
119+
{ text: "YES", onPress: () => BackHandler.exitApp() }
120+
]);
121+
return true;
122+
};
32123
33-
```jsx
34124
componentDidMount() {
35-
this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
125+
this.backHandler = BackHandler.addEventListener(
126+
"hardwareBackPress",
127+
this.backAction
128+
);
36129
}
37130
38131
componentWillUnmount() {
39-
this.backHandler.remove()
132+
this.backHandler.remove();
40133
}
41134
42-
handleBackPress = () => {
43-
this.goBack(); // works best when the goBack is async
135+
render() {
136+
return (
137+
<View style={styles.container}>
138+
<Text style={styles.text}>Click Back button!</Text>
139+
</View>
140+
);
141+
}
142+
}
143+
144+
const styles = StyleSheet.create({
145+
container: {
146+
flex: 1,
147+
alignItems: "center",
148+
justifyContent: "center"
149+
},
150+
text: {
151+
fontSize: 18,
152+
fontWeight: "bold"
153+
}
154+
});
155+
```
156+
157+
<block class="endBlock syntax" />
158+
159+
`BackHandler.addEventListener` creates an event listener & returns a `NativeEventSubscription` object which should be cleared using `NativeEventSubscription.remove` method.
160+
161+
Additionally `BackHandler.removeEventListener` can also be used to clear the event listener. Ensure the callback has the reference to the same function used in the `addEventListener` call as shown the following example οΉ£
162+
163+
<div class="toggler">
164+
<ul role="tablist" class="toggle-syntax">
165+
<li id="functional" class="button-functional" aria-selected="false" role="tab" tabindex="0" aria-controls="functionaltab" onclick="displayTabs('syntax', 'functional')">
166+
Function Component Example
167+
</li>
168+
<li id="classical" class="button-classical" aria-selected="false" role="tab" tabindex="0" aria-controls="classicaltab" onclick="displayTabs('syntax', 'classical')">
169+
Class Component Example
170+
</li>
171+
</ul>
172+
</div>
173+
174+
<block class="functional syntax" />
175+
176+
```SnackPlayer name=BackHandler&supportedPlatforms=android
177+
import React, { useEffect } from "react";
178+
import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
179+
180+
export default function App() {
181+
const backAction = () => {
182+
Alert.alert("Hold on!", "Are you sure you want to go back?", [
183+
{
184+
text: "Cancel",
185+
onPress: () => null,
186+
style: "cancel"
187+
},
188+
{ text: "YES", onPress: () => BackHandler.exitApp() }
189+
]);
44190
return true;
191+
};
192+
193+
useEffect(() => {
194+
BackHandler.addEventListener("hardwareBackPress", backAction);
195+
196+
return () =>
197+
BackHandler.removeEventListener("hardwareBackPress", backAction);
198+
}, []);
199+
200+
return (
201+
<View style={styles.container}>
202+
<Text style={styles.text}>Click Back button!</Text>
203+
</View>
204+
);
205+
}
206+
207+
const styles = StyleSheet.create({
208+
container: {
209+
flex: 1,
210+
alignItems: "center",
211+
justifyContent: "center"
212+
},
213+
text: {
214+
fontSize: 18,
215+
fontWeight: "bold"
45216
}
217+
});
46218
```
47219

48-
Lifecycle alternative:
220+
<block class="classical syntax" />
221+
222+
```SnackPlayer name=BackHandler&supportedPlatforms=android
223+
import React, { Component } from "react";
224+
import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
225+
226+
export default class App extends Component {
227+
backAction = () => {
228+
Alert.alert("Hold on!", "Are you sure you want to go back?", [
229+
{
230+
text: "Cancel",
231+
onPress: () => null,
232+
style: "cancel"
233+
},
234+
{ text: "YES", onPress: () => BackHandler.exitApp() }
235+
]);
236+
return true;
237+
};
49238
50-
```jsx
51239
componentDidMount() {
52-
this.backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
53-
this.goBack(); // works best when the goBack is async
54-
return true;
55-
});
240+
BackHandler.addEventListener("hardwareBackPress", this.backAction);
56241
}
57242
58243
componentWillUnmount() {
59-
this.backHandler.remove();
244+
BackHandler.removeEventListener("hardwareBackPress", this.backAction);
245+
}
246+
247+
render() {
248+
return (
249+
<View style={styles.container}>
250+
<Text style={styles.text}>Click Back button!</Text>
251+
</View>
252+
);
253+
}
254+
}
255+
256+
const styles = StyleSheet.create({
257+
container: {
258+
flex: 1,
259+
alignItems: "center",
260+
justifyContent: "center"
261+
},
262+
text: {
263+
fontSize: 18,
264+
fontWeight: "bold"
60265
}
266+
});
61267
```
62268

269+
<block class="endBlock syntax" />
270+
271+
## Usage with React Navigation
272+
273+
If you are using React Navigation to navigate across different screens, you can follow their guide on [Custom Android back button behaviour](https://reactnavigation.org/docs/custom-android-back-button-handling/)
274+
275+
## Backhandler hook
276+
277+
[React Native Hooks](https://github.com/react-native-community/hooks#usebackhandler) has a nice `useBackHandler` hook which will simplify the process of setting up event listeners.
278+
63279
---
64280

65281
# Reference

0 commit comments

Comments
Β (0)