Skip to content

Commit 85594e2

Browse files
committed
fix(bottom-sheet-native): resolve React Native Reanimated worklet function errors
1 parent 19e559c commit 85594e2

File tree

3 files changed

+60
-34
lines changed

3 files changed

+60
-34
lines changed

packages/pluggableWidgets/bottom-sheet-native/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- Fixed React Native Reanimated worklet function errors by properly memoizing snap points.
912
- Updated react-native-reanimated to v3.16.7
1013

1114
## [5.0.1] - 2025-7-7

packages/pluggableWidgets/bottom-sheet-native/src/components/CustomModalSheet.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createElement, ReactElement, ReactNode, useEffect, useRef, useState } from "react";
1+
import { createElement, ReactElement, ReactNode, useEffect, useRef, useState, useMemo } from "react";
22
import { InteractionManager, LayoutChangeEvent, Modal, Pressable, SafeAreaView, StyleSheet, View } from "react-native";
33
import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetView } from "@gorhom/bottom-sheet";
44
import { EditableValue, ValueStatus } from "mendix";
@@ -17,6 +17,13 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
1717
const [currentStatus, setCurrentStatus] = useState(false);
1818
const isAvailable = props.triggerAttribute && props.triggerAttribute.status === ValueStatus.Available;
1919

20+
const snapPoints = useMemo(() => {
21+
if (height === 0) {
22+
return ["90%"];
23+
}
24+
return [height - Number(defaultPaddings.paddingBottom)];
25+
}, [height]);
26+
2027
const onLayoutFullscreenHandler = (event: LayoutChangeEvent): void => {
2128
const layoutHeight = event.nativeEvent.layout.height;
2229
if (layoutHeight > 0 && layoutHeight !== height) {
@@ -34,7 +41,7 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
3441
bottomSheetRef.current?.close();
3542
setCurrentStatus(false);
3643
}
37-
}, [props.triggerAttribute, currentStatus]);
44+
}, [props.triggerAttribute, currentStatus, isAvailable]);
3845

3946
if (height === 0) {
4047
return (
@@ -44,14 +51,12 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
4451
);
4552
}
4653

47-
const snapPoints = [height - Number(defaultPaddings.paddingBottom)];
48-
4954
const isOpen =
5055
props.triggerAttribute &&
5156
props.triggerAttribute.status === ValueStatus.Available &&
5257
props.triggerAttribute.value;
5358

54-
const renderBackdrop = (backdropProps: BottomSheetBackdropProps) => (
59+
const renderBackdrop = (backdropProps: BottomSheetBackdropProps): ReactElement => (
5560
<Pressable style={{ flex: 1 }} onPress={close}>
5661
<BottomSheetBackdrop
5762
{...backdropProps}
@@ -63,7 +68,7 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
6368
</Pressable>
6469
);
6570

66-
const handleSheetChanges = (index: number) => {
71+
const handleSheetChanges = (index: number): void => {
6772
if (!isAvailable) {
6873
return;
6974
}
@@ -79,7 +84,7 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
7984
}
8085
};
8186

82-
const close = () => {
87+
const close = (): void => {
8388
bottomSheetRef.current?.close();
8489
};
8590

packages/pluggableWidgets/bottom-sheet-native/src/components/ExpandingDrawer.tsx

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createElement, ReactNode, ReactElement, useCallback, useState, useRef, Children } from "react";
1+
import { createElement, ReactNode, ReactElement, useCallback, useState, useRef, Children, useMemo } from "react";
22
import { Dimensions, LayoutChangeEvent, SafeAreaView, StyleSheet, View } from "react-native";
33
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
44
import { BottomSheetStyle } from "../ui/Styles";
@@ -26,23 +26,29 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
2626
const isSmallContentValid = Children.count(props.smallContent) > 0;
2727
const isLargeContentValid = Children.count(props.largeContent) > 0;
2828

29-
const onLayoutHandlerHeader = (event: LayoutChangeEvent): void => {
30-
const height = event.nativeEvent.layout.height;
31-
if (height > 0 && height <= maxHeight) {
32-
setHeightHeader(height);
33-
}
34-
};
29+
const onLayoutHandlerHeader = useCallback(
30+
(event: LayoutChangeEvent): void => {
31+
const height = event.nativeEvent.layout.height;
32+
if (height > 0 && height <= maxHeight) {
33+
setHeightHeader(height);
34+
}
35+
},
36+
[maxHeight]
37+
);
3538

36-
const onLayoutHandlerContent = (event: LayoutChangeEvent): void => {
37-
const height = event.nativeEvent.layout.height;
38-
if (height > 0) {
39-
if (height <= maxHeight) {
40-
setHeightContent(height);
41-
} else if (!props.fullscreenContent) {
42-
setHeightContent(maxHeight);
39+
const onLayoutHandlerContent = useCallback(
40+
(event: LayoutChangeEvent): void => {
41+
const height = event.nativeEvent.layout.height;
42+
if (height > 0) {
43+
if (height <= maxHeight) {
44+
setHeightContent(height);
45+
} else if (!props.fullscreenContent) {
46+
setHeightContent(maxHeight);
47+
}
4348
}
44-
}
45-
};
49+
},
50+
[maxHeight, props.fullscreenContent]
51+
);
4652

4753
const onLayoutFullscreenHandler = (event: LayoutChangeEvent): void => {
4854
const height = event.nativeEvent.layout.height;
@@ -54,6 +60,19 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
5460
const containerStyle =
5561
props.fullscreenContent && isOpen ? props.styles.containerWhenExpandedFullscreen : props.styles.container;
5662

63+
const snapPoints = useMemo(() => {
64+
if (props.fullscreenContent && heightContent) {
65+
return [fullscreenHeight, heightContent, heightHeader];
66+
}
67+
if (props.fullscreenContent) {
68+
return [fullscreenHeight, heightHeader];
69+
}
70+
if (isLargeContentValid) {
71+
return [heightContent, heightHeader];
72+
}
73+
return [heightHeader];
74+
}, [props.fullscreenContent, heightContent, fullscreenHeight, heightHeader, isLargeContentValid]);
75+
5776
const renderContent = useCallback((): ReactNode => {
5877
const content = (
5978
<View onLayout={onLayoutHandlerContent} pointerEvents="box-none">
@@ -77,7 +96,15 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
7796
);
7897
}
7998
return content;
80-
}, [props.smallContent, props.largeContent, props.fullscreenContent, isOpen, fullscreenHeight]);
99+
}, [
100+
props.smallContent,
101+
props.largeContent,
102+
props.fullscreenContent,
103+
fullscreenHeight,
104+
isSmallContentValid,
105+
onLayoutHandlerContent,
106+
onLayoutHandlerHeader
107+
]);
81108

82109
if (props.fullscreenContent && fullscreenHeight === 0) {
83110
return (
@@ -91,18 +118,9 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
91118
return <View style={{ position: "absolute", bottom: -maxHeight }}>{renderContent()}</View>;
92119
}
93120

94-
const snapPoints =
95-
props.fullscreenContent && heightContent
96-
? [fullscreenHeight, heightContent, heightHeader]
97-
: props.fullscreenContent
98-
? [fullscreenHeight, heightHeader]
99-
: isLargeContentValid
100-
? [heightContent, heightHeader]
101-
: [heightHeader];
102-
103121
const collapsedIndex = 0;
104122

105-
const onChange = (index: number) => {
123+
const onChange = (index: number): void => {
106124
const hasOpened = lastIndexRef === -1 && index === 0;
107125
const hasClosed = index === -1;
108126

0 commit comments

Comments
 (0)