├── .github └── FUNDING.yml ├── .gitignore ├── BackHandler.android.js ├── BackHandler.ios.js ├── BackHandler.web.js ├── LICENSE ├── README.md ├── index.d.ts ├── index.js └── package.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [vonovak] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /BackHandler.android.js: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { BackHandler } from 'react-native'; 3 | import { useFocusEffect } from '@react-navigation/native'; 4 | 5 | export const useAndroidBackHandler = (onBackPress) => ( 6 | useFocusEffect(( 7 | useCallback(() => { 8 | const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress); 9 | 10 | return () => subscription.remove(); 11 | }, [onBackPress]) 12 | )) 13 | ); 14 | 15 | export const AndroidBackHandler = ({ onBackPress, children = null }) => { 16 | useAndroidBackHandler(onBackPress); 17 | 18 | return children; 19 | }; 20 | -------------------------------------------------------------------------------- /BackHandler.ios.js: -------------------------------------------------------------------------------- 1 | export const AndroidBackHandler = ({ children }) => children || null; 2 | export const useAndroidBackHandler = () => {}; 3 | -------------------------------------------------------------------------------- /BackHandler.web.js: -------------------------------------------------------------------------------- 1 | export const AndroidBackHandler = ({ children }) => children || null; 2 | export const useAndroidBackHandler = () => {}; 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Vojtech Novak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-navigation-backhandler 2 | 3 | Easily handle Android back button behavior with React-Navigation. 4 | 5 | > NOTE use version 1 of this package for `react-navigation` version 4 and lower 6 | > 7 | > use version 2 of this package for `react-navigation` version 5 and later 8 | 9 | ## Installation 10 | 11 | Install with npm: 12 | 13 | ```sh 14 | $ npm install react-navigation-backhandler 15 | ``` 16 | 17 | Install with yarn: 18 | 19 | ```sh 20 | $ yarn add react-navigation-backhandler 21 | ``` 22 | 23 | ## Usage 24 | 25 | The following snippet demonstrates the usage. Note that `onBackButtonPressAndroid` will only be called if `SomeComponent` is placed in a screen that is focused (the one user is directly interacting with). 26 | 27 | Behind the scenes, the `onBackButtonPressAndroid` handler is registered before a screen is focused, and unregistered before going away from it, leaving you with a declarative interface to interact with. Internally, this package uses apis that are provided by `react-navigation`. 28 | 29 | You may use `useAndroidBackHandler` or `AndroidBackHandler` component anywhere in your app's React tree, it does not need to be placed directly in the screen component. 30 | 31 | There are two ways of using this library: 32 | 33 | 1. [As hook](#use-as-hook) 34 | 1. [As component](#use-as-component) 35 | 36 | ### Use as hook 37 | 38 | ```js 39 | import { useAndroidBackHandler } from "react-navigation-backhandler"; 40 | 41 | const SomeComponent = () => { 42 | const onBackPress = useCallback(() => { 43 | /* 44 | * Returning `true` denotes that we have handled the event, 45 | * and react-navigation's lister will not get called, thus not popping the screen. 46 | * 47 | * Returning `false` will cause the event to bubble up and react-navigation's listener will pop the screen. 48 | * */ 49 | 50 | if (youWantToHandleTheBackButtonPress) { 51 | // do something 52 | return true 53 | } 54 | 55 | return false 56 | }, []) 57 | 58 | useAndroidBackHandler(onBackPress) 59 | 60 | return 61 | } 62 | ``` 63 | 64 | ### Use as component 65 | 66 | > **Note:** You can also use the component "inline" without children: `` 67 | 68 | ```js 69 | import { AndroidBackHandler } from "react-navigation-backhandler"; 70 | 71 | class SomeComponent extends React.Component { 72 | onBackButtonPressAndroid = () => { 73 | /* 74 | * Returning `true` from `onBackButtonPressAndroid` denotes that we have handled the event, 75 | * and react-navigation's lister will not get called, thus not popping the screen. 76 | * 77 | * Returning `false` will cause the event to bubble up and react-navigation's listener will pop the screen. 78 | * */ 79 | 80 | if (youWantToHandleTheBackButtonPress) { 81 | // do something 82 | return true; 83 | } 84 | 85 | return false; 86 | }; 87 | 88 | render() { 89 | return ( 90 | 91 | 92 | 93 | ); 94 | } 95 | } 96 | ``` 97 | 98 | ## Warning 99 | 100 | The package was only tested to be used in screens in stack navigator, other use cases may not work. 101 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "react-navigation-backhandler" { 2 | import { FC, PropsWithChildren } from "react"; 3 | 4 | export interface AndroidBackHandlerProperties { 5 | onBackPress: () => boolean; 6 | } 7 | 8 | export const AndroidBackHandler: FC>; 9 | 10 | export function useAndroidBackHandler(onBackPress: () => boolean): void; 11 | } 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | export * from './BackHandler'; 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-navigation-backhandler", 3 | "version": "2.0.3", 4 | "description": "Easily handle Android back button with react-navigation", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/vonovak/react-navigation-backhandler.git" 12 | }, 13 | "keywords": [ 14 | "react-navigation", 15 | "react-native" 16 | ], 17 | "peerDependencies": { 18 | "react": "*", 19 | "@react-navigation/native": "*", 20 | "react-native": "*" 21 | }, 22 | "author": "Vojtech Novak", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/vonovak/react-navigation-backhandler/issues" 26 | }, 27 | "homepage": "https://github.com/vonovak/react-navigation-backhandler#readme" 28 | } 29 | --------------------------------------------------------------------------------