Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bottom Sheet does not close on physical back button press #556

Closed
Ripul01 opened this issue Aug 1, 2021 · 12 comments
Closed

Bottom Sheet does not close on physical back button press #556

Ripul01 opened this issue Aug 1, 2021 · 12 comments
Labels
question Further information is requested

Comments

@Ripul01
Copy link

Ripul01 commented Aug 1, 2021

Ask your Question

Hello, The bottom sheet does not seem to close when the physical back button is pressed in android. I have tried it on the issue template too and the same issue appears. Upon pressing the back button, the window behind the bottom sheet pops and the app quits on the starting screen. Should this happen and does anyone know of a fix for this issue?

@Ripul01 Ripul01 added the question Further information is requested label Aug 1, 2021
@gorhom
Copy link
Owner

gorhom commented Aug 5, 2021

Hi @Ripul01 , i think this should be handling by you not the library. you could look for back button handler implementation on trigger the close method on the bottom sheet 👍

@gorhom gorhom closed this as completed Aug 5, 2021
@Ripul01
Copy link
Author

Ripul01 commented Aug 6, 2021

Thank you very much. It seems I was confused on a trivial issue.

@Ripul01
Copy link
Author

Ripul01 commented Aug 6, 2021

Hey Gorhom, I had another question. How will we check if the bottom sheet is open to handle that case and if not handle the normal case?

@arnnis
Copy link

arnnis commented Dec 14, 2021

@Ripul01

Hey Gorhom, I had another question. How will we check if the bottom sheet is open to handle that case and if not handle the normal case?

Use onChange prop and in the BackHandler check if current index > -1

@nguyenbathanh
Copy link

const { dismiss } = useBottomSheetModal()

useEffect(() => {
  const handleBackButton = () => {
    return dismiss() // dismiss() returns true/false, it means there is any instance of Bottom Sheet visible on current screen.
  }

  BackHandler.addEventListener('hardwareBackPress', handleBackButton);
  return () => {
    BackHandler.removeEventListener('hardwareBackPress', handleBackButton);
  };
}, []);

@jzxchiang1
Copy link

const { dismiss } = useBottomSheetModal()

useEffect(() => {
  const handleBackButton = () => {
    return dismiss() // dismiss() returns true/false, it means there is any instance of Bottom Sheet visible on current screen.
  }

  BackHandler.addEventListener('hardwareBackPress', handleBackButton);
  return () => {
    BackHandler.removeEventListener('hardwareBackPress', handleBackButton);
  };
}, []);

That doesn't work for me with react-navigation.

@jzxchiang1
Copy link

jzxchiang1 commented Jan 22, 2022

This is a working solution that plays well with react-navigation.

  const [isShowing, setIsShowing] = useState<boolean>(false);

  useFocusEffect(
    useCallback(() => {
      // addEventListener and removeEventListener must refer to the same function
      const onBackPress = () => {
        if (isShowing) {
          modalRef.current?.dismiss();
          return true; // TS complains if handler doesn't return a boolean
        } else {
          return false;
        }
      };
      BackHandler.addEventListener('hardwareBackPress', onBackPress);
      return () =>
        BackHandler.removeEventListener('hardwareBackPress', onBackPress);
    }, [modalRef, isShowing]),
  );

  return (
    <BottomSheetModal
      ref={modalRef}
      ...
      onChange={idx => setIsShowing(idx > -1)}>
      ...
    </BottomSheetModal>
  );

@Hesowcharov
Copy link

One more snippet of how to handle the hardware back button when your bottom sheet is in front of a user (i.e. visible):

/**
 * hook that dismisses the bottom sheet on the hardware back button press if it is visible
 * @param bottomSheetRef ref to the bottom sheet which is going to be closed/dismissed on the back press
 */
export const useBottomSheetBackHandler = (bottomSheetRef: React.RefObject<BottomSheetModal | null>) => {
  const backHandlerSubscriptionRef = useRef<NativeEventSubscription | null>(null)
  const handleSheetPositionChange = useCallback<NonNullable<BottomSheetModalProps['onChange']>>((index) => {
    const isBottomSheetVisible = index >= 0
    if (isBottomSheetVisible && !backHandlerSubscriptionRef.current) {
      // setup the back handler if the bottom sheet is right in front of the user
      backHandlerSubscriptionRef.current = BackHandler.addEventListener('hardwareBackPress', () => {
        bottomSheetRef.current?.dismiss()
        return true
      })
    } else if (!isBottomSheetVisible) {
      backHandlerSubscriptionRef.current?.remove()
      backHandlerSubscriptionRef.current = null
    }
  }, [bottomSheetRef, backHandlerSubscriptionRef])
  return { handleSheetPositionChange }
}

Then somewhere in your code pass the returned handler to onChange prop:

...
const { handleSheetPositionChange } = useBottomSheetBackHandler(bottomSheetRef)
...

return (
    <BottomSheetModal
        ref={bottomSheetRef}
        onChange={handleSheetPositionChange}>
    </BottomSheetModal>
)

@dinhduongson
Copy link

@Hesowcharov thank you so much. It's work!!!!!!

@vanenshi
Copy link

vanenshi commented Feb 8, 2022

@gorhom is it possible to add this functionality to the modal base code, and control it by props?

like:

<BottomSheetModal
  ref={bottomSheetRef}
  ...
  dismissOnBackAndroid={false}>
</BottomSheetModal>

@pierroo
Copy link

pierroo commented Dec 19, 2022

awesome solution @Hesowcharov ;
But what if we are managing the display of the BottomSheet through useState rather than ref?

For example I have a :

{
        isNotifSheet && (
          <BottomSheet index={0} onClose={() => setIsNotifSheet(false)} onChange={handleSheetPositionChange}
...
)
}

So there is no ref associated to it.
For some reason, it does work even without ref.

BUT, randomly, the back button seems to be broken when using it and once the bottomsheet is closed;
Like the default backbutton was overwritten as expected but not back to normal once bottomsheet is closed.

@dkahdwk
Copy link

dkahdwk commented Mar 20, 2023

...
const ref = useRef<BottomSheet>(null);
const [currentIndex, setCurrentIndex] = useState<number>(-1);
...

const onBackPress = () => {
  if (ref !== null) {
    ref.current?.close();
    return true;
  }
};

useEffect(() => {
  if (currentIndex !== -1) {
    BackHandler.addEventListener('hardwareBackPress', onBackPress);

    return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress);
  }
}, [currentIndex]);

return (
  <BottomSheet
    ref={ref}
    onChange={(index) => {
      setCurrentIndex(index);
    }
   ...
   >
  </BottomSheet>
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

10 participants