react-native-bottom-sheet icon indicating copy to clipboard operation
react-native-bottom-sheet copied to clipboard

[v4] | [v2] BottomSheetModal failing to present on iOS

Open walterholohan opened this issue 2 years ago β€’ 52 comments
trafficstars

Bug

We just recently updated RN to 0.72.5 and react-native-reanimated to 3.5.4 and released it to production over the weekend. And then we started to get reports from our users that the modals were failing to appear. I will attach some videos below but we were unable to reproduce it on a simulator or a real device however we have ~150,000 MAU so after 24 hours we had over 10 users who were affected.

We had users on iOS 16.x and iOS 17.x who were affected

To unblock our users I had to set animateOnMount to false which makes me believe the issue is with the opening animation of the modal and reanimated

Environment info

Library Version
@gorhom/bottom-sheet 4.4.7
react-native 0.72.5
react-native-reanimated 3.5.4
react-native-gesture-handler 2.13.1

Steps To Reproduce

  1. User tries to press on Link Activity and you can see the modal briefly flashes
  2. User tries to press on Referral Code and again the modal flashes and closes

https://github.com/gorhom/react-native-bottom-sheet/assets/5293650/746ad438-0a85-436a-98c1-d59f051ca18c

Reproducible sample code

can attach an example of code if necessary but I was just following to docs for BottomSheetModal

walterholohan avatar Oct 04 '23 12:10 walterholohan

Same happening to us, affecting at least 15 users so far. We couldn't get a repro yet either.

Bottom sheet 4.5.1 React native 0.72.5 Reanimated 3.5.4

SrAnthony avatar Oct 04 '23 13:10 SrAnthony

Same here, animateOnMount to false does fix the issue but really low number of users affected.

LouisKraemer avatar Oct 04 '23 13:10 LouisKraemer

Thanks @SrAnthony and @LouisKraemer good to hear that you are also experiencing the same issue for your users. I haven't been able to deepdive into the animation implementation but hopefully @gorhom can give some insight or potential avenue's we can explore for a fix

walterholohan avatar Oct 04 '23 22:10 walterholohan

Same here, we are also using expo sdk 49. It also happens on android

karbone4 avatar Oct 05 '23 13:10 karbone4

Same issue here, more and more users are starting to complain about this - also unable to reproduce for us on simulator or our testing devices. This is happening for our users on both v4 and v5.

enchorb avatar Oct 05 '23 21:10 enchorb

Some of our users are affected as well. I think I managed to reproduce it, at least on IOS: Activate the Reduce Motion accessibility setting in your Iphone, restart your app then bottomsheets are not opening anymore.

Reanimated recently added support for this setting -> https://docs.swmansion.com/react-native-reanimated/docs/guides/accessibility/

hatem-72 avatar Oct 06 '23 09:10 hatem-72

wow great spot @hatem-72 , did you manage to create a patch for this lib?

walterholohan avatar Oct 06 '23 11:10 walterholohan

For the moment, I've only disabled the opening animation for users with reduced motion :

import { useReducedMotion } from 'react-native-reanimated';
import { BottomSheetModal } from '@gorhom/bottom-sheet';

// ...

function MyComponent() {
    const reducedMotion = useReducedMotion();

    return <BottomSheetModal
        // ...
        animateOnMount={!reducedMotion}
    >
        // ...
    </BottomSheetModal>
}

hatem-72 avatar Oct 06 '23 11:10 hatem-72

@hatem-72 great find! reached out to 2 users who were having this issue and they both had it enabled.

enchorb avatar Oct 06 '23 11:10 enchorb

Can we buy @hatem-72 a coffee?

walterholohan avatar Oct 06 '23 11:10 walterholohan

Thanks @hatem-72 for the fix.

I have another bug, I can't dismiss the bottom modal 2 times. If I dismiss, open it again, I can't dismiss it. I found a workaround by overriding ref :

const reducedMotion = useReducedMotion();
useImperativeHandle(
    bottomModalRef,
    () => ({
        dismiss: () => {
            if (reducedMotion) {
                ref?.current?.snapToPosition(0);
            } else {
                ref?.current?.dismiss();
            }
        }
    }),
    [reducedMotion]
);

karbone4 avatar Oct 06 '23 13:10 karbone4

@karbone4 I am unable to reproduce your bug. It works for me

walterholohan avatar Oct 06 '23 14:10 walterholohan

Hello everyone!

Setting animateOnMount to false causes many weird issues (can't dismiss the modal, sometimes you need to click twice to get it open) . Another temporary fix is to add this patch (thanks to @efstathiosntonas) to override reduced motion to false in reanimated 3.5.4:

diff --git a/node_modules/react-native-reanimated/src/reanimated2/PlatformChecker.ts b/node_modules/react-native-reanimated/src/reanimated2/PlatformChecker.ts
index 9b3fcb1..0111380 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/PlatformChecker.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/PlatformChecker.ts
@@ -49,5 +49,5 @@ export function isReducedMotion() {
       ? // @ts-ignore Fallback if `window` is undefined.
         !window.matchMedia('(prefers-reduced-motion: no-preference)').matches
       : false
-    : (global as localGlobal)._REANIMATED_IS_REDUCED_MOTION ?? false;
+    : false;
 }

leymytel avatar Oct 10 '23 10:10 leymytel

Also observed on a device running Android 10 with reduce motion option enabled

nihilenz avatar Oct 18 '23 14:10 nihilenz

Also hitting this issue, rather than disabling the reduce motion detection for Reanimated globally we went with conditionally supplying our own animation config only when required. There are still some minor quirks when dismissing the sheet, but it does at least open and work correctly:

const reduceMotionEnabled = useReducedMotion();
const overrideConfig = useBottomSheetSpringConfigs({
  damping: 500,
  stiffness: 1000,
  mass: 3,
  overshootClamping: true,
  restDisplacementThreshold: 10,
  restSpeedThreshold: 10,
  reduceMotion: ReduceMotion.Never,
});

return (
  <BottomSheetModal
    /*
    There's a bug in BottomSheet which means that sheets will fail to open when reduce motion is enabled. Manually
    providing an animation config with `reduceMotion: ReduceMotion.Never` fixes this, but it does introduce a bit
    of jank when dismissing the sheet. This is a tradeoff we're willing to make for the sake of sheets at least
    working when reduce motion is enabled.

    @see https://github.com/gorhom/react-native-bottom-sheet/issues/1560
    */
    animationConfigs={reduceMotionEnabled ? overrideConfig : undefined}
    // other config here...
  />
);

The animation config was lifted from https://github.com/gorhom/react-native-bottom-sheet/blob/65b5dc03e673c25b3b41af954e1f13fe7668a339/src/constants.ts#L68-L75 to keep thre behaviour the same as before, I noticed that there's a platform fork and on Android the animation using a timing config, so you could probably use that based on platform, but we were happy enough with the spring config for both platforms.

levibuzolic avatar Oct 23 '23 00:10 levibuzolic

In fact, I think this problem is fundamentally a problem with the changes in Reanimated that were made when the BottomSheet version was upgraded, although BottomSheet itself handles reduceOption in a way.

Simple problem solving can be done in the other comment1 and comment2 posted above. But I think the fundamental solution is to allow Reanimated itself to control the relevant settings.

So I posted my opinion and the cause I identified on Reanimated.(https://github.com/software-mansion/react-native-reanimated/discussions/5314#issuecomment-5314) We ask for your interest. Let’s solve this problem related to accessibility together!

Gyogle avatar Oct 27 '23 07:10 Gyogle

As I see, reduced motion is also enabled if low power mode is active and device battery is <= 10%. Almost all screenshots from our user reports shows that their device battery are <= 10%. Apple mentions this here, under Low Power Mode title. So it may be a wider issue than we think, not related with accessibility settings only.

andac-ozcan avatar Oct 30 '23 11:10 andac-ozcan

I think, reduced motion is also enabled if low power mode is active and device battery is <= 10%. Almost all screenshots from our user bug reports shows their device battery is <= 10%. Apple mentions this here, under Low Power Mode title. So it may be a wider issue than we think, not related with accessibility settings only.

Thank you very much. This is the root cause of my case

nguyenhoanganhdev avatar Nov 01 '23 08:11 nguyenhoanganhdev

Although I tested setting reducedMotion to false, it's not a viable solution because the problem still appears from time to time. I think it's a fundamental problem with how Reanimated and BottomSheet works as @Gyogle states.

CostasCF avatar Nov 05 '23 12:11 CostasCF

Inspired by the above answer, main difference being the import of ANIMATION_CONFIGS:

import { useBottomSheetSpringConfigs } from "@gorhom/bottom-sheet"
import { ANIMATION_CONFIGS } from "@gorhom/bottom-sheet/src/constants"
import { Platform } from "react-native"
import { ReduceMotion, WithTimingConfig, useReducedMotion } from "react-native-reanimated"

/**
 * https://github.com/gorhom/react-native-bottom-sheet/issues/1560
 *
 * Usage:
 * ```
 * const animationConfigs = useBottomSheetAnimationConfigsReducedMotionWorkaround()
 * <BottomSheetModal animationConfigs={animationConfigs} ...>
 * ```
 *
 * @returns
 */
export function useBottomSheetAnimationConfigsReducedMotionWorkaround():
  | WithTimingConfig
  | undefined {
  const reducedMotion = useReducedMotion()
  const iOSAnimationConfigWithoutReducedMotion = useBottomSheetSpringConfigs({
    ...ANIMATION_CONFIGS,
    reduceMotion: ReduceMotion.Never,
  })

  if (Platform.OS !== "ios" || !reducedMotion) return undefined

  return iOSAnimationConfigWithoutReducedMotion
}

mattijsf avatar Nov 13 '23 14:11 mattijsf

@gorhom would the above be worth a v4 patch release?

mattijsf avatar Nov 14 '23 08:11 mattijsf

Tried the fix by @levibuzolic / @mattijsf. That works most of the time but got some weird issues when having multiple BottomSheets. Also tried disabling motion, that was very weird. Currently using the reanimated patch by @leymytel, that seems to be working fine.

@gorhom It would be really great if you can look into this.

salman-ar-sar avatar Nov 20 '23 10:11 salman-ar-sar

In my case, one of our users had the "Reduce Motion" option enabled and that caused the modals to not open. It was solved as follows

import {useReducedMotion} from 'react-native-reanimated'

...
const reducedMotion = useReducedMotion()

<BottomModal animateOnMount={!reducedMotion}

@hatem-72 Thanks!!

jlmosconi avatar Nov 21 '23 19:11 jlmosconi

@leymytel this patch includes animation for users who have enabled motion reduction, I think not everyone will be happy with this behavior

marshallcool avatar Nov 27 '23 14:11 marshallcool

This issue will cause a lot of users to be completely unable to use the Apps that uses this library. If you have time, can you please have a look? @gorhom πŸ’—

YaoHuiJi avatar Dec 02 '23 11:12 YaoHuiJi

I am experiencing the same issue with version 3.5.4, but am not having issues with 3.3.0

keithluchtel avatar Dec 05 '23 17:12 keithluchtel

@karbone4 Same issue where I can't close modal the second time... I tried using your fix but it doesn't seem to be working. Any advice? Thanks!

`const reducedMotion = useReducedMotion();

useImperativeHandle( bottomSheetModalRef, () => ({ dismiss: () => { if (reducedMotion) { ref?.current?.snapToPosition(0); } else { ref?.current?.dismiss(); } }, }), [reducedMotion], );

return ( <BottomSheetModal animateOnMount={!reducedMotion} backdropComponent={BottomSheetBackdrop} ref={bottomSheetModalRef} index={0} snapPoints={snapPoints}> <SafeAreaView style={styles.container}> <ScrollView> <View style={styles.navContainer}> <TouchableOpacity onPress={() => { bottomSheetModalRef.current?.dismiss(); }}> `

henryteng07 avatar Dec 26 '23 09:12 henryteng07

@karbone4 I got it! Just use ref.current.close() instead of ref.current.dismiss()

henryteng07 avatar Dec 26 '23 09:12 henryteng07

Is this working in the latest version? Same issue.

mMarcos208 avatar Jan 11 '24 19:01 mMarcos208

Is this working in the latest version? Same issue.

TomWq avatar Jan 13 '24 10:01 TomWq