fix: assigning to read-only property 'reduceMotion'
Motivation
Upgrading the package to version 4.6.3 results in the following error when rendering BottomSheet in the development.
ERROR TypeError: Cannot assign to read-only property 'reduceMotion'
This error is located at:
in AnimatedComponent(View)
in Unknown (created by PanGestureHandler)
in PanGestureHandler (created by BottomSheetDraggableViewComponent)
in BottomSheetDraggableViewComponent (created by BottomSheet)
in RCTView (created by View)
in View (created by AnimatedComponent(View))
in AnimatedComponent(View)
in Unknown (created by BottomSheet)
in RCTView (created by View)
in View (created by AnimatedComponent(View))
in AnimatedComponent(View)
in Unknown (created by BottomSheet)
in RCTView (created by View)
in View (created by BottomSheetContainerComponent)
in BottomSheetContainerComponent (created by BottomSheet)
in BottomSheetGestureHandlersProvider (created by BottomSheet)
in BottomSheet (created by BottomSheet)
...
in AppContainer
in main(RootComponent), js engine: hermes
Cause
Function animate inside src/utilities/animate.ts uses worklet and you cannot modify the objects inside the worklet, as explained here: https://github.com/software-mansion/react-native-reanimated/issues/5430#issuecomment-1831453991.
Solution
We have to add reduceMotion if:
- ReduceMotion exists (it does not in earlier versions of react-native-reanimated)
- the passed config is not undefined (to preserve current behaviour with default configs)
It would be better to do it in one place or we can extract the logic to the utility function
env-info
expo-env-info 1.2.0 environment info:
System:
OS: macOS 14.4.1
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.11.1 - ~/.volta/tools/image/node/20.11.1/bin/node
Yarn: 1.22.22 - ~/.volta/tools/image/yarn/1.22.22/bin/yarn
npm: 10.7.0 - ~/projects/alergeek/intu/app/node_modules/.bin/npm
Watchman: 2023.12.04.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.14.3 - /Users/frydson/.rbenv/shims/pod
SDKs:
iOS SDK:
Platforms: DriverKit 23.4, iOS 17.4, macOS 14.4, tvOS 17.4, visionOS 1.1, watchOS 10.4
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8512546
Xcode: 15.3/15E204a - /usr/bin/xcodebuild
npmPackages:
@expo/metro-config: 0.18.1 => 0.18.1
babel-preset-expo: 11.0.0 => 11.0.0
expo: 51.0.1 => 51.0.1
react: 18.2.0 => 18.2.0
react-native: 0.74.1 => 0.74.1
Expo Workflow: bare
Nice! This warning is really annoying. Could we assign a maintainer for review? Other PRs here don't seem to get much traction π
Very nice, thanks! I just added this patch and works really well! No more warnings
diff --git a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx
index f20e3dc..9d190f5 100644
--- a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx
+++ b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx
@@ -21,6 +21,7 @@ import Animated, {
useWorkletCallback,
WithSpringConfig,
WithTimingConfig,
+ ReduceMotion,
} from 'react-native-reanimated';
import { State } from 'react-native-gesture-handler';
import {
@@ -98,7 +99,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
//#region extract props
const {
// animations configurations
- animationConfigs: _providedAnimationConfigs,
+ animationConfigs,
// configurations
index: _providedIndex = 0,
@@ -172,6 +173,20 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
} = props;
//#endregion
+ //#region animations configurations
+ const _providedAnimationConfigs = useMemo(() => {
+ if (!animationConfigs) {
+ return undefined;
+ }
+
+ if (ReduceMotion) {
+ animationConfigs.reduceMotion = ReduceMotion.Never;
+ }
+
+ return animationConfigs;
+ }, [animationConfigs]);
+ //#endregion
+
//#region layout variables
/**
* This variable is consider an internal variable,
@@ -722,6 +737,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
* force animation configs from parameters, if provided
*/
if (configs !== undefined) {
+ if (ReduceMotion) {
+ configs.reduceMotion = ReduceMotion.Never;
+ }
animatedPosition.value = animate({
point: position,
configs,
diff --git a/node_modules/@gorhom/bottom-sheet/src/constants.ts b/node_modules/@gorhom/bottom-sheet/src/constants.ts
index cc8fb9f..6aaa5a3 100644
--- a/node_modules/@gorhom/bottom-sheet/src/constants.ts
+++ b/node_modules/@gorhom/bottom-sheet/src/constants.ts
@@ -1,5 +1,5 @@
import { Dimensions, Platform } from 'react-native';
-import Animated, { Easing } from 'react-native-reanimated';
+import Animated, { Easing, ReduceMotion } from 'react-native-reanimated';
const { height: WINDOW_HEIGHT, width: WINDOW_WIDTH } = Dimensions.get('window');
const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('screen');
@@ -72,11 +72,13 @@ const ANIMATION_CONFIGS_IOS = {
overshootClamping: true,
restDisplacementThreshold: 10,
restSpeedThreshold: 10,
+ ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}),
};
const ANIMATION_CONFIGS_ANDROID = {
duration: ANIMATION_DURATION,
easing: ANIMATION_EASING,
+ ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}),
};
const ANIMATION_CONFIGS =
diff --git a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts
index 81fec5b..0ce4c9a 100644
--- a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts
+++ b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts
@@ -4,8 +4,6 @@ import {
withTiming,
withSpring,
AnimationCallback,
- // @ts-ignore
- ReduceMotion,
} from 'react-native-reanimated';
import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants';
@@ -28,14 +26,6 @@ export const animate = ({
configs = ANIMATION_CONFIGS;
}
- // Users might have an accessibililty setting to reduce motion turned on.
- // This prevents the animation from running when presenting the sheet, which results in
- // the bottom sheet not even appearing so we need to override it to ensure the animation runs.
- if (ReduceMotion) {
- // @ts-ignore
- configs.reduceMotion = ReduceMotion.Never;
- }
-
// detect animation type
const type =
'duration' in configs || 'easing' in configs
Very nice, thanks! I just added this patch and works really well! No more warnings
diff --git a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx index f20e3dc..9d190f5 100644 --- a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx +++ b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx @@ -21,6 +21,7 @@ import Animated, { useWorkletCallback, WithSpringConfig, WithTimingConfig, + ReduceMotion, } from 'react-native-reanimated'; import { State } from 'react-native-gesture-handler'; import { @@ -98,7 +99,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( //#region extract props const { // animations configurations - animationConfigs: _providedAnimationConfigs, + animationConfigs, // configurations index: _providedIndex = 0, @@ -172,6 +173,20 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( } = props; //#endregion + //#region animations configurations + const _providedAnimationConfigs = useMemo(() => { + if (!animationConfigs) { + return undefined; + } + + if (ReduceMotion) { + animationConfigs.reduceMotion = ReduceMotion.Never; + } + + return animationConfigs; + }, [animationConfigs]); + //#endregion + //#region layout variables /** * This variable is consider an internal variable, @@ -722,6 +737,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( * force animation configs from parameters, if provided */ if (configs !== undefined) { + if (ReduceMotion) { + configs.reduceMotion = ReduceMotion.Never; + } animatedPosition.value = animate({ point: position, configs, diff --git a/node_modules/@gorhom/bottom-sheet/src/constants.ts b/node_modules/@gorhom/bottom-sheet/src/constants.ts index cc8fb9f..6aaa5a3 100644 --- a/node_modules/@gorhom/bottom-sheet/src/constants.ts +++ b/node_modules/@gorhom/bottom-sheet/src/constants.ts @@ -1,5 +1,5 @@ import { Dimensions, Platform } from 'react-native'; -import Animated, { Easing } from 'react-native-reanimated'; +import Animated, { Easing, ReduceMotion } from 'react-native-reanimated'; const { height: WINDOW_HEIGHT, width: WINDOW_WIDTH } = Dimensions.get('window'); const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('screen'); @@ -72,11 +72,13 @@ const ANIMATION_CONFIGS_IOS = { overshootClamping: true, restDisplacementThreshold: 10, restSpeedThreshold: 10, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS_ANDROID = { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS = diff --git a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts index 81fec5b..0ce4c9a 100644 --- a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts +++ b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts @@ -4,8 +4,6 @@ import { withTiming, withSpring, AnimationCallback, - // @ts-ignore - ReduceMotion, } from 'react-native-reanimated'; import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants'; @@ -28,14 +26,6 @@ export const animate = ({ configs = ANIMATION_CONFIGS; } - // Users might have an accessibililty setting to reduce motion turned on. - // This prevents the animation from running when presenting the sheet, which results in - // the bottom sheet not even appearing so we need to override it to ensure the animation runs. - if (ReduceMotion) { - // @ts-ignore - configs.reduceMotion = ReduceMotion.Never; - } - // detect animation type const type = 'duration' in configs || 'easing' in configs
awesome
when it will be merged?
@gorhom
still hope and wait it merged
please merge @gorhom.
This solved flawlessly, omg I was with this warning for days now, Thanks bro
What's up with the merger?
Our app is on fire, please merge this now π¬ π§βπ
I'm still waiting for merge π₯±
All of us are waiting π
We are waiting for @gorhom to merge, please.
we are waiting for the merge @gorhom
please merge π
For everyone waiting - you can patch the package locally in your projects using patch-package: https://github.com/ds300/patch-package
Waiting for this as well
Any updates on this PR?
ππ»please mergeππ»
+1 ππ»
+1 please merge
ππ
import {
WithSpringConfig,
WithTimingConfig,
withTiming,
withSpring,
AnimationCallback,
ReduceMotion,
} from 'react-native-reanimated';
import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants';
interface AnimateParams {
point: number;
velocity?: number;
configs?: WithSpringConfig | WithTimingConfig;
onComplete?: AnimationCallback;
}
export const animate = ({
point,
configs = undefined,
velocity = 0,
onComplete,
}: AnimateParams) => {
'worklet';
if (!configs) {
configs = ANIMATION_CONFIGS;
}
// Users might have an accessibility setting to reduce motion turned on.
// This prevents the animation from running when presenting the sheet, which results in
// the bottom sheet not even appearing so we need to override it to ensure the animation runs.
let newConfigs = configs;
if (ReduceMotion) {
newConfigs = { ...configs, reduceMotion: ReduceMotion.Never };
}
// detect animation type
const type =
'duration' in newConfigs || 'easing' in newConfigs
? ANIMATION_METHOD.TIMING
: ANIMATION_METHOD.SPRING;
if (type === ANIMATION_METHOD.TIMING) {
return withTiming(point, newConfigs as WithTimingConfig, onComplete);
} else {
return withSpring(
point,
Object.assign({ velocity }, newConfigs) as WithSpringConfig,
onComplete
);
}
};
Very nice, thanks! I just added this patch and works really well! No more warnings
diff --git a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx index f20e3dc..9d190f5 100644 --- a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx +++ b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx @@ -21,6 +21,7 @@ import Animated, { useWorkletCallback, WithSpringConfig, WithTimingConfig, + ReduceMotion, } from 'react-native-reanimated'; import { State } from 'react-native-gesture-handler'; import { @@ -98,7 +99,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( //#region extract props const { // animations configurations - animationConfigs: _providedAnimationConfigs, + animationConfigs, // configurations index: _providedIndex = 0, @@ -172,6 +173,20 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( } = props; //#endregion + //#region animations configurations + const _providedAnimationConfigs = useMemo(() => { + if (!animationConfigs) { + return undefined; + } + + if (ReduceMotion) { + animationConfigs.reduceMotion = ReduceMotion.Never; + } + + return animationConfigs; + }, [animationConfigs]); + //#endregion + //#region layout variables /** * This variable is consider an internal variable, @@ -722,6 +737,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( * force animation configs from parameters, if provided */ if (configs !== undefined) { + if (ReduceMotion) { + configs.reduceMotion = ReduceMotion.Never; + } animatedPosition.value = animate({ point: position, configs, diff --git a/node_modules/@gorhom/bottom-sheet/src/constants.ts b/node_modules/@gorhom/bottom-sheet/src/constants.ts index cc8fb9f..6aaa5a3 100644 --- a/node_modules/@gorhom/bottom-sheet/src/constants.ts +++ b/node_modules/@gorhom/bottom-sheet/src/constants.ts @@ -1,5 +1,5 @@ import { Dimensions, Platform } from 'react-native'; -import Animated, { Easing } from 'react-native-reanimated'; +import Animated, { Easing, ReduceMotion } from 'react-native-reanimated'; const { height: WINDOW_HEIGHT, width: WINDOW_WIDTH } = Dimensions.get('window'); const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('screen'); @@ -72,11 +72,13 @@ const ANIMATION_CONFIGS_IOS = { overshootClamping: true, restDisplacementThreshold: 10, restSpeedThreshold: 10, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS_ANDROID = { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS = diff --git a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts index 81fec5b..0ce4c9a 100644 --- a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts +++ b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts @@ -4,8 +4,6 @@ import { withTiming, withSpring, AnimationCallback, - // @ts-ignore - ReduceMotion, } from 'react-native-reanimated'; import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants'; @@ -28,14 +26,6 @@ export const animate = ({ configs = ANIMATION_CONFIGS; } - // Users might have an accessibililty setting to reduce motion turned on. - // This prevents the animation from running when presenting the sheet, which results in - // the bottom sheet not even appearing so we need to override it to ensure the animation runs. - if (ReduceMotion) { - // @ts-ignore - configs.reduceMotion = ReduceMotion.Never; - } - // detect animation type const type = 'duration' in configs || 'easing' in configs
That's really helpful while I'm waiting for the release. Save my time Thank you.
Please merge!!!
dies slowly
after applying this patch, i still get warning "Tried to modify key reduceMotion of an object which has been already passed to a worklet." when using bottom sheet with detached option on: <BottomSheetModal detached ... />
after applying this patch, i still get warning "Tried to modify key
reduceMotionof an object which has been already passed to a worklet." when using bottom sheet with detached option on: <BottomSheetModal detached ... />
How you patch that? can you show me your patch file? I did and it really work.
@beepov It works for me too, but only for normal ones, not for detached ones. In my case i use a custom detached one with animations and other stuffs. Here is my patch (yarn v3, react native 0.74.3).
Very nice, thanks! I just added this patch and works really well! No more warnings
diff --git a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx index f20e3dc..9d190f5 100644 --- a/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx +++ b/node_modules/@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx @@ -21,6 +21,7 @@ import Animated, { useWorkletCallback, WithSpringConfig, WithTimingConfig, + ReduceMotion, } from 'react-native-reanimated'; import { State } from 'react-native-gesture-handler'; import { @@ -98,7 +99,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( //#region extract props const { // animations configurations - animationConfigs: _providedAnimationConfigs, + animationConfigs, // configurations index: _providedIndex = 0, @@ -172,6 +173,20 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( } = props; //#endregion + //#region animations configurations + const _providedAnimationConfigs = useMemo(() => { + if (!animationConfigs) { + return undefined; + } + + if (ReduceMotion) { + animationConfigs.reduceMotion = ReduceMotion.Never; + } + + return animationConfigs; + }, [animationConfigs]); + //#endregion + //#region layout variables /** * This variable is consider an internal variable, @@ -722,6 +737,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>( * force animation configs from parameters, if provided */ if (configs !== undefined) { + if (ReduceMotion) { + configs.reduceMotion = ReduceMotion.Never; + } animatedPosition.value = animate({ point: position, configs, diff --git a/node_modules/@gorhom/bottom-sheet/src/constants.ts b/node_modules/@gorhom/bottom-sheet/src/constants.ts index cc8fb9f..6aaa5a3 100644 --- a/node_modules/@gorhom/bottom-sheet/src/constants.ts +++ b/node_modules/@gorhom/bottom-sheet/src/constants.ts @@ -1,5 +1,5 @@ import { Dimensions, Platform } from 'react-native'; -import Animated, { Easing } from 'react-native-reanimated'; +import Animated, { Easing, ReduceMotion } from 'react-native-reanimated'; const { height: WINDOW_HEIGHT, width: WINDOW_WIDTH } = Dimensions.get('window'); const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('screen'); @@ -72,11 +72,13 @@ const ANIMATION_CONFIGS_IOS = { overshootClamping: true, restDisplacementThreshold: 10, restSpeedThreshold: 10, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS_ANDROID = { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, + ...(ReduceMotion ? { reduceMotion: ReduceMotion.Never } : {}), }; const ANIMATION_CONFIGS = diff --git a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts index 81fec5b..0ce4c9a 100644 --- a/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts +++ b/node_modules/@gorhom/bottom-sheet/src/utilities/animate.ts @@ -4,8 +4,6 @@ import { withTiming, withSpring, AnimationCallback, - // @ts-ignore - ReduceMotion, } from 'react-native-reanimated'; import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants'; @@ -28,14 +26,6 @@ export const animate = ({ configs = ANIMATION_CONFIGS; } - // Users might have an accessibililty setting to reduce motion turned on. - // This prevents the animation from running when presenting the sheet, which results in - // the bottom sheet not even appearing so we need to override it to ensure the animation runs. - if (ReduceMotion) { - // @ts-ignore - configs.reduceMotion = ReduceMotion.Never; - } - // detect animation type const type = 'duration' in configs || 'easing' in configs
it's working perfectly.