From 0c4a8d743fea3f236601445e9ea4de2685b8cdd9 Mon Sep 17 00:00:00 2001 From: Github Date: Mon, 19 May 2025 13:39:41 +0200 Subject: [PATCH 1/2] Optimize useAnimatedHighlightStyle to reduce unnecessary recalculations --- src/hooks/useAnimatedHighlightStyle/index.ts | 32 ++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/hooks/useAnimatedHighlightStyle/index.ts b/src/hooks/useAnimatedHighlightStyle/index.ts index 96ecd9c9f9db..5ff702aa66e2 100644 --- a/src/hooks/useAnimatedHighlightStyle/index.ts +++ b/src/hooks/useAnimatedHighlightStyle/index.ts @@ -65,12 +65,32 @@ export default function useAnimatedHighlightStyle({ const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus(); const theme = useTheme(); - const highlightBackgroundStyle = useAnimatedStyle(() => ({ - backgroundColor: interpolateColor(repeatableProgress.get(), [0, 1], [backgroundColor ?? theme.appBG, highlightColor ?? theme.border]), - height: height ? interpolate(nonRepeatableProgress.get(), [0, 1], [0, height]) : 'auto', - opacity: interpolate(nonRepeatableProgress.get(), [0, 1], [0, 1]), - borderRadius, - })); + const highlightBackgroundStyle = useAnimatedStyle(() => { + 'worklet'; + + // This code runs both on the JS thread (once for setup) and on the UI thread (for actual animation). + // To avoid accessing Reanimated shared values (like .value) on the JS thread, + // we guard the JS execution path with `_WORKLET`. This ensures we return a safe fallback style + // during the JS pass and avoid any crashes or unexpected behavior. + if (!_WORKLET) { + return { + backgroundColor: backgroundColor ?? theme.appBG, + height: height ?? 'auto', + opacity: 0, + borderRadius, + }; + } + + const repeatableValue = repeatableProgress.get(); + const nonRepeatableValue = nonRepeatableProgress.get(); + + return { + backgroundColor: interpolateColor(repeatableValue, [0, 1], [backgroundColor ?? theme.appBG, highlightColor ?? theme.border]), + height: height ? interpolate(nonRepeatableValue, [0, 1], [0, height]) : 'auto', + opacity: interpolate(nonRepeatableValue, [0, 1], [0, 1]), + borderRadius, + }; + }, [borderRadius, height, backgroundColor, highlightColor, theme.appBG, theme.border]); React.useEffect(() => { if (!shouldHighlight || startHighlight) { From bb2e1d4fea98cfe9a213a7405d9b5fa505bbae90 Mon Sep 17 00:00:00 2001 From: Github Date: Tue, 20 May 2025 15:03:00 +0200 Subject: [PATCH 2/2] fix: remove non-worklet fallback --- src/hooks/useAnimatedHighlightStyle/index.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/hooks/useAnimatedHighlightStyle/index.ts b/src/hooks/useAnimatedHighlightStyle/index.ts index 5ff702aa66e2..dabae528444a 100644 --- a/src/hooks/useAnimatedHighlightStyle/index.ts +++ b/src/hooks/useAnimatedHighlightStyle/index.ts @@ -68,19 +68,6 @@ export default function useAnimatedHighlightStyle({ const highlightBackgroundStyle = useAnimatedStyle(() => { 'worklet'; - // This code runs both on the JS thread (once for setup) and on the UI thread (for actual animation). - // To avoid accessing Reanimated shared values (like .value) on the JS thread, - // we guard the JS execution path with `_WORKLET`. This ensures we return a safe fallback style - // during the JS pass and avoid any crashes or unexpected behavior. - if (!_WORKLET) { - return { - backgroundColor: backgroundColor ?? theme.appBG, - height: height ?? 'auto', - opacity: 0, - borderRadius, - }; - } - const repeatableValue = repeatableProgress.get(); const nonRepeatableValue = nonRepeatableProgress.get();