From 081d10a4e2425640a0c40605250af4dd0c2599ed Mon Sep 17 00:00:00 2001 From: Jacek Pudysz Date: Fri, 24 Apr 2026 16:01:21 +0200 Subject: [PATCH] fix: use animated theme with scoped themes --- .../src/reanimated/useAnimatedTheme.native.ts | 29 ++++++++++++++----- .../src/reanimated/useAnimatedTheme.ts | 27 ++++++++++++----- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/packages/unistyles/src/reanimated/useAnimatedTheme.native.ts b/packages/unistyles/src/reanimated/useAnimatedTheme.native.ts index 3800485b6..6ffb2012e 100644 --- a/packages/unistyles/src/reanimated/useAnimatedTheme.native.ts +++ b/packages/unistyles/src/reanimated/useAnimatedTheme.native.ts @@ -1,22 +1,37 @@ -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { type SharedValue, useSharedValue } from 'react-native-reanimated' import type { UnistylesTheme } from '../types' -import { StyleSheet, UnistyleDependency, UnistylesRuntime } from '../specs' +import { StyleSheet, UnistyleDependency, UnistylesRuntime, UnistylesShadowRegistry } from '../specs' export const useAnimatedTheme = () => { - const theme = useSharedValue(UnistylesRuntime.getTheme()) + const [scopedTheme, setScopedTheme] = useState( + () => UnistylesShadowRegistry.getScopedTheme() as UnistylesTheme | undefined, + ) + const theme = useSharedValue(UnistylesRuntime.getTheme(scopedTheme)) + const maybeNewScopedTheme = UnistylesShadowRegistry.getScopedTheme() as UnistylesTheme | undefined + + if (scopedTheme !== maybeNewScopedTheme) { + setScopedTheme(maybeNewScopedTheme) + theme.set(UnistylesRuntime.getTheme(maybeNewScopedTheme)) + } useEffect(() => { - const dispose = StyleSheet.addChangeListener((changedDependencies) => { - if (changedDependencies.includes(UnistyleDependency.Theme)) { - theme.set(UnistylesRuntime.getTheme()) + const dispose = StyleSheet.addChangeListener(changedDependencies => { + if (!changedDependencies.includes(UnistyleDependency.Theme)) { + return + } + + if (scopedTheme) { + return } + + theme.set(UnistylesRuntime.getTheme()) }) return () => dispose() - }, []) + }, [scopedTheme]) return theme as SharedValue } diff --git a/packages/unistyles/src/reanimated/useAnimatedTheme.ts b/packages/unistyles/src/reanimated/useAnimatedTheme.ts index 4d3d56d87..17d6be929 100644 --- a/packages/unistyles/src/reanimated/useAnimatedTheme.ts +++ b/packages/unistyles/src/reanimated/useAnimatedTheme.ts @@ -1,23 +1,36 @@ -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { type SharedValue, useSharedValue } from 'react-native-reanimated' import type { UnistylesTheme } from '../types' -import { UnistyleDependency, UnistylesRuntime } from '../specs' +import { UnistyleDependency, UnistylesRuntime, UnistylesShadowRegistry } from '../specs' import { services } from '../web/services' export const useAnimatedTheme = () => { - const theme = useSharedValue(UnistylesRuntime.getTheme()) + const [scopedTheme, setScopedTheme] = useState( + () => UnistylesShadowRegistry.getScopedTheme() as UnistylesTheme | undefined, + ) + const theme = useSharedValue(UnistylesRuntime.getTheme(scopedTheme)) + const maybeNewScopedTheme = UnistylesShadowRegistry.getScopedTheme() as UnistylesTheme | undefined + + if (scopedTheme !== maybeNewScopedTheme) { + setScopedTheme(maybeNewScopedTheme) + theme.set(UnistylesRuntime.getTheme(maybeNewScopedTheme)) + } useEffect(() => { - const dispose = services.listener.addListeners([UnistyleDependency.Theme], () => - theme.set(UnistylesRuntime.getTheme()), - ) + const dispose = services.listener.addListeners([UnistyleDependency.Theme], () => { + if (scopedTheme) { + return + } + + theme.set(UnistylesRuntime.getTheme()) + }) return () => { dispose() } - }, []) + }, [scopedTheme]) return theme as SharedValue }