Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Fix BackHandle callback undefined cause crash issue (#48388)
Summary: ### Error message: we got an error ``` t[n] is not a function. (In 't[n]()', 't[n]' is undefined) \n <unknown> (index.bundle:317:168:317) ``` it related the BackHandle execute handle function. ### Investigation result our project has screen files`App.tsx`, `Dashboard.tsx`, and `Profile.tsx`. When launching the app, the screen order is `App.tsx` -> `Dashboard.tsx`, then user can switch to `Profile.tsx` For `App.tsx` and `Dashboard.tsx`, we just prevent the hardware button action use `usePreventHardwareBackPressEffect()` in the first line of screen code. ```js export const useHardwareBackPressEffect = (goBack?: () => boolean): void => { useEffect(() => { if (goBack) { BackHandler.addEventListener("hardwareBackPress", goBack); return () => { BackHandler.removeEventListener("hardwareBackPress", goBack); }; } return undefined; }, [ goBack ]); }; export const usePreventHardwareBackPressEffect = (): void => useHardwareBackPressEffect(() => true); ``` currently, `_backPressSubscriptions ` has 2 callback functions. then user switch to `Profile.tsx` screen, and has the below code for hardwareback button and the second doesn't `return true`: ```js // first one usePreventHardwareBackPressEffect(); ... // second one useEffect(() => { const backButtonListener = BackHandler.addEventListener( "hardwareBackPress", () => navigate(Navigation.Login); ); return () => backButtonListener.remove(); }); ``` currently, `_backPressSubscriptions ` has 4 callback functions, include previous 2 and new 2 of `Profile.tsx`. When the user press hardwareback button, it will navigate to the login screen, so the issue occurs: the latest callback will be executed first, then the navigation will let the screen unmount, which will destroy the effect, so the code removing 2 hardwareBackPress callback of `Profile.tsx` by executed ```js return () => { BackHandler.removeEventListener("hardwareBackPress", goBack); }; ``` After the navigation ends and the loop is restored, the init `i` is 3, then `i--`, `i` is 2, then `_backPressSubscriptions[2]` is `undefined` now and executes as a function, so the app crashes. ```js for (let i = _backPressSubscriptions.length - 1; i >= 0; i--) { if (_backPressSubscriptions[i]()) { return; } } ``` that's the issue I met. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID] [FIXED] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [ANDROID] [FIXED] - Fix BackHandle callback undefined cause crash issue Pull Request resolved: #48388 Reviewed By: blakef Differential Revision: D67648077 Pulled By: rshest fbshipit-source-id: 5ca685b0c0c474ef11772fd803743968ec2d912e
- Loading branch information