diff --git a/.eslintrc.js b/.eslintrc.js index b40f29345..1b2a3e41d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,5 +4,11 @@ module.exports = { rules: { 'no-console': ['error', { allow: ['warn', 'error'] }], 'prettier/prettier': 'error', + 'react-hooks/exhaustive-deps': [ + 'error', + { + additionalHooks: '(useAnimatedStyle|useDerivedValue|useAnimatedProps)', + }, + ], }, }; diff --git a/example/src/components/customBackground/CustomBackground.tsx b/example/src/components/customBackground/CustomBackground.tsx index 175e0e964..57a3392f2 100644 --- a/example/src/components/customBackground/CustomBackground.tsx +++ b/example/src/components/customBackground/CustomBackground.tsx @@ -13,14 +13,17 @@ const CustomBackgroundComponent: React.FC = ({ animatedIndex, }) => { //#region styles - const containerAnimatedStyle = useAnimatedStyle(() => ({ - // @ts-ignore - backgroundColor: interpolateColor( - animatedIndex.value, - [0, 1], - ['#ffffff', '#a8b5eb'] - ), - })); + const containerAnimatedStyle = useAnimatedStyle( + () => ({ + // @ts-ignore + backgroundColor: interpolateColor( + animatedIndex.value, + [0, 1], + ['#ffffff', '#a8b5eb'] + ), + }), + [animatedIndex.value] + ); const containerStyle = useMemo( () => [styles.container, style, containerAnimatedStyle], [style, containerAnimatedStyle] diff --git a/example/src/components/customFooter/CustomFooter.tsx b/example/src/components/customFooter/CustomFooter.tsx index 71b31bd4e..1d3731cf8 100644 --- a/example/src/components/customFooter/CustomFooter.tsx +++ b/example/src/components/customFooter/CustomFooter.tsx @@ -36,7 +36,7 @@ const CustomFooterComponent = ({ return { transform: [{ rotate: `${arrowRotate}rad` }], }; - }, []); + }, [animatedIndex.value]); const arrowStyle = useMemo( () => [arrowAnimatedStyle, styles.arrow], [arrowAnimatedStyle] diff --git a/example/src/components/customHandle/CustomHandle.tsx b/example/src/components/customHandle/CustomHandle.tsx index b5eb59bf6..0cc100878 100644 --- a/example/src/components/customHandle/CustomHandle.tsx +++ b/example/src/components/customHandle/CustomHandle.tsx @@ -22,8 +22,15 @@ const CustomHandleComponent: React.FC = ({ }) => { //#region animations - const indicatorTransformOriginY = useDerivedValue(() => - interpolate(animatedIndex.value, [0, 1, 2], [-1, 0, 1], Extrapolate.CLAMP) + const indicatorTransformOriginY = useDerivedValue( + () => + interpolate( + animatedIndex.value, + [0, 1, 2], + [-1, 0, 1], + Extrapolate.CLAMP + ), + [animatedIndex.value] ); //#endregion @@ -40,7 +47,7 @@ const CustomHandleComponent: React.FC = ({ borderTopLeftRadius: borderTopRadius, borderTopRightRadius: borderTopRadius, }; - }); + }, [animatedIndex.value]); const leftIndicatorStyle = useMemo( () => ({ ...styles.indicator, @@ -66,7 +73,7 @@ const CustomHandleComponent: React.FC = ({ } ), }; - }); + }, [animatedIndex.value, indicatorTransformOriginY.value]); const rightIndicatorStyle = useMemo( () => ({ ...styles.indicator, @@ -92,7 +99,7 @@ const CustomHandleComponent: React.FC = ({ } ), }; - }); + }, [animatedIndex.value, indicatorTransformOriginY.value]); //#endregion // render diff --git a/example/src/screens/integrations/map/LocationListBottomSheet.tsx b/example/src/screens/integrations/map/LocationListBottomSheet.tsx index 35d0e940e..e8f6f5295 100644 --- a/example/src/screens/integrations/map/LocationListBottomSheet.tsx +++ b/example/src/screens/integrations/map/LocationListBottomSheet.tsx @@ -37,9 +37,12 @@ export const LocationListBottomSheet = forwardRef< //#endregion //#region styles - const scrollViewAnimatedStyle = useAnimatedStyle(() => ({ - opacity: index.value, - })); + const scrollViewAnimatedStyle = useAnimatedStyle( + () => ({ + opacity: index.value, + }), + [index.value] + ); const scrollViewStyle = useMemo( () => [styles.scrollView, scrollViewAnimatedStyle], [scrollViewAnimatedStyle] diff --git a/example/src/screens/integrations/map/Weather.tsx b/example/src/screens/integrations/map/Weather.tsx index 044b256c2..981eabd0c 100644 --- a/example/src/screens/integrations/map/Weather.tsx +++ b/example/src/screens/integrations/map/Weather.tsx @@ -54,7 +54,7 @@ const Weather = ({ animatedIndex, animatedPosition }: WeatherProps) => { }, ], }; - }, [height, screenHeight]); + }, [animatedIndex.value, animatedPosition.value, height, screenHeight]); const containerStyle = useMemo( () => [ styles.container, diff --git a/package.json b/package.json index c67231d21..3ed2eff72 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "eslint-plugin-prettier": "^4.2.1", "husky": "^4.3.8", "lint-staged": "^13.2.2", + "metro-react-native-babel-preset": "^0.77.0", "prettier": "^2.8.8", "react": "18.2.0", "react-native": "0.73.1", diff --git a/src/components/bottomSheet/BottomSheet.tsx b/src/components/bottomSheet/BottomSheet.tsx index 1d0cab2b8..8a8c0a2a9 100644 --- a/src/components/bottomSheet/BottomSheet.tsx +++ b/src/components/bottomSheet/BottomSheet.tsx @@ -195,7 +195,7 @@ const BottomSheetComponent = forwardRef( return $modal ? _animatedContainerHeight.value - verticalInset : _animatedContainerHeight.value; - }, [$modal, topInset, bottomInset]); + }, [topInset, bottomInset, $modal, _animatedContainerHeight.value]); const animatedContainerOffset = useReactiveSharedValue( _providedContainerOffset ?? INITIAL_CONTAINER_OFFSET ) as Animated.SharedValue; @@ -214,7 +214,8 @@ const BottomSheetComponent = forwardRef( maxDynamicContentSize ); const animatedHighestSnapPoint = useDerivedValue( - () => animatedSnapPoints.value[animatedSnapPoints.value.length - 1] + () => animatedSnapPoints.value[animatedSnapPoints.value.length - 1], + [animatedSnapPoints.value] ); const animatedClosedPosition = useDerivedValue(() => { let closedPosition = animatedContainerHeight.value; @@ -224,9 +225,10 @@ const BottomSheetComponent = forwardRef( } return closedPosition; - }, [$modal, detached, bottomInset]); + }, [animatedContainerHeight.value, $modal, detached, bottomInset]); const animatedSheetHeight = useDerivedValue( - () => animatedContainerHeight.value - animatedHighestSnapPoint.value + () => animatedContainerHeight.value - animatedHighestSnapPoint.value, + [animatedContainerHeight.value, animatedHighestSnapPoint.value] ); const animatedCurrentIndex = useReactiveSharedValue( animateOnMount ? -1 : _providedIndex @@ -274,7 +276,13 @@ const BottomSheetComponent = forwardRef( isHandleHeightCalculated && isSnapPointsNormalized ); - }); + }, [ + _providedContainerHeight, + animatedContainerHeight.value, + animatedHandleHeight, + animatedSnapPoints.value, + handleComponent, + ]); const isInTemporaryPosition = useSharedValue(false); const isForcedClosing = useSharedValue(false); @@ -399,7 +407,12 @@ const BottomSheetComponent = forwardRef( } return SCROLLABLE_STATE.LOCKED; - }); + }, [ + animatedAnimationState.value, + animatedKeyboardState.value, + animatedScrollableOverrideState.value, + animatedSheetState.value, + ]); // dynamic const animatedContentHeightMax = useDerivedValue(() => { const keyboardHeightInContainer = animatedKeyboardHeightInContainer.value; @@ -513,7 +526,18 @@ const BottomSheetComponent = forwardRef( } return currentIndex; - }, [android_keyboardInputMode]); + }, [ + android_keyboardInputMode, + animatedAnimationSource.value, + animatedAnimationState.value, + animatedContainerHeight.value, + animatedCurrentIndex.value, + animatedNextPositionIndex.value, + animatedPosition.value, + animatedSnapPoints.value, + isInTemporaryPosition.value, + isLayoutCalculated.value, + ]); //#endregion //#region private methods @@ -1258,7 +1282,12 @@ const BottomSheetComponent = forwardRef( configs: _providedAnimationConfigs, }), }; - }, [animatedContentHeightMax, enableDynamicSizing, animatedContentHeight]); + }, [ + enableDynamicSizing, + animatedContentHeight.value, + animatedContentHeightMax.value, + _providedAnimationConfigs, + ]); const contentContainerStyle = useMemo( () => [styles.contentContainer, contentContainerAnimatedStyle], [contentContainerAnimatedStyle] @@ -1277,7 +1306,7 @@ const BottomSheetComponent = forwardRef( return { paddingBottom: animatedContainerHeight.value, }; - }, [detached]); + }, [animatedContainerHeight.value, detached]); const contentMaskContainerStyle = useMemo( () => [styles.contentMaskContainer, contentMaskContainerAnimatedStyle], [contentMaskContainerAnimatedStyle] @@ -1424,7 +1453,8 @@ const BottomSheetComponent = forwardRef( } } animateToPosition(nextPosition, animationSource, 0, animationConfig); - } + }, + [] ); /** @@ -1547,7 +1577,8 @@ const BottomSheetComponent = forwardRef( if (_providedAnimatedPosition) { _providedAnimatedPosition.value = _animatedPosition + topInset; } - } + }, + [] ); /** @@ -1559,7 +1590,8 @@ const BottomSheetComponent = forwardRef( if (_providedAnimatedIndex) { _providedAnimatedIndex.value = _animatedIndex; } - } + }, + [] ); /** diff --git a/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx b/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx index f89064a89..3e789ea07 100644 --- a/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx +++ b/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx @@ -96,15 +96,18 @@ const BottomSheetBackdropComponent = ({ //#endregion //#region styles - const containerAnimatedStyle = useAnimatedStyle(() => ({ - opacity: interpolate( - animatedIndex.value, - [-1, disappearsOnIndex, appearsOnIndex], - [0, 0, opacity], - Extrapolation.CLAMP - ), - flex: 1, - })); + const containerAnimatedStyle = useAnimatedStyle( + () => ({ + opacity: interpolate( + animatedIndex.value, + [-1, disappearsOnIndex, appearsOnIndex], + [0, 0, opacity], + Extrapolation.CLAMP + ), + flex: 1, + }), + [animatedIndex.value, appearsOnIndex, disappearsOnIndex, opacity] + ); const containerStyle = useMemo( () => [styles.container, style, containerAnimatedStyle], [style, containerAnimatedStyle] diff --git a/src/components/bottomSheetDebugView/ReText.webx.tsx b/src/components/bottomSheetDebugView/ReText.webx.tsx index 94fc67c38..f63f93d53 100644 --- a/src/components/bottomSheetDebugView/ReText.webx.tsx +++ b/src/components/bottomSheetDebugView/ReText.webx.tsx @@ -26,7 +26,7 @@ const ReText = (props: TextProps) => { : _providedValue.value; return `${text}: ${value}`; - }); + }, [_providedValue, text]); //region effects useAnimatedReaction( @@ -35,7 +35,8 @@ const ReText = (props: TextProps) => { textRef.current?.setNativeProps({ text: result, }); - } + }, + [] ); //endregion diff --git a/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx b/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx index 2bce722bf..f7dd6bb5c 100644 --- a/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx +++ b/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx @@ -27,9 +27,12 @@ function BottomSheetRefreshControlComponent({ //#endregion //#region variables - const animatedProps = useAnimatedProps(() => ({ - enabled: animatedScrollableState.value === SCROLLABLE_STATE.UNLOCKED, - })); + const animatedProps = useAnimatedProps( + () => ({ + enabled: animatedScrollableState.value === SCROLLABLE_STATE.UNLOCKED, + }), + [animatedScrollableState.value] + ); const gesture = useMemo( () => Gesture.Simultaneous( diff --git a/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx b/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx index 9162b665a..84d305dd5 100644 --- a/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx +++ b/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx @@ -108,7 +108,7 @@ export function createBottomSheetScrollableComponent( ? animatedFooterHeight.value : 0, }), - [enableFooterMarginAdjustment] + [animatedFooterHeight.value, enableFooterMarginAdjustment] ); const containerStyle = useMemo(() => { return enableFooterMarginAdjustment diff --git a/src/hooks/useKeyboard.ts b/src/hooks/useKeyboard.ts index 2cf672fe4..be8f00bcc 100644 --- a/src/hooks/useKeyboard.ts +++ b/src/hooks/useKeyboard.ts @@ -119,7 +119,8 @@ export const useKeyboard = () => { if (result && params.length > 0) { handleKeyboardEvent(params[0], params[1], params[2], params[3]); } - } + }, + [] ); //#endregion diff --git a/src/hooks/useNormalizedSnapPoints.ts b/src/hooks/useNormalizedSnapPoints.ts index 99953a5e6..5d3207fbb 100644 --- a/src/hooks/useNormalizedSnapPoints.ts +++ b/src/hooks/useNormalizedSnapPoints.ts @@ -88,6 +88,14 @@ export const useNormalizedSnapPoints = ( _normalizedSnapPoints.indexOf(dynamicSnapPoint); return _normalizedSnapPoints; - }, [snapPoints, enableDynamicSizing, maxDynamicContentSize]); + }, [ + containerHeight.value, + snapPoints, + enableDynamicSizing, + handleHeight.value, + contentHeight.value, + maxDynamicContentSize, + dynamicSnapPointIndex, + ]); return [normalizedSnapPoints, dynamicSnapPointIndex]; }; diff --git a/yarn.lock b/yarn.lock index 8616dfdc0..fdaeeefa0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6109,6 +6109,51 @@ metro-minify-terser@0.80.2: dependencies: terser "^5.15.0" +metro-react-native-babel-preset@^0.77.0: + version "0.77.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.77.0.tgz#47457eca8e36b77156afbe790247a70dbb40faaa" + integrity sha512-HPPD+bTxADtoE4y/4t1txgTQ1LVR6imOBy7RMHUsqMVTbekoi8Ph5YI9vKX2VMPtVWeFt0w9YnCSLPa76GcXsA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.18.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" + "@babel/plugin-proposal-numeric-separator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.20.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.20.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.20.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.20.0" + "@babel/plugin-transform-flow-strip-types" "^7.20.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.4.0" + metro-resolver@0.80.2: version "0.80.2" resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.2.tgz#16066b763221a5c233d818ab81544b8b95d16c72" @@ -7217,6 +7262,11 @@ react-refresh@^0.14.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== +react-refresh@^0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" + integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== + react-shallow-renderer@^16.15.0: version "16.15.0" resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457"