From 8f95c1ebf29d92bfff030f948de54726735c1c62 Mon Sep 17 00:00:00 2001 From: huymobile Date: Sun, 30 Aug 2026 18:24:23 +0700 Subject: [PATCH] Fix useColorScheme subscription lifecycle --- .../useColorScheme/__tests__/index-test.js | 38 +++++++++++++++++++ .../src/exports/useColorScheme/index.js | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 packages/react-native-web/src/exports/useColorScheme/__tests__/index-test.js diff --git a/packages/react-native-web/src/exports/useColorScheme/__tests__/index-test.js b/packages/react-native-web/src/exports/useColorScheme/__tests__/index-test.js new file mode 100644 index 0000000000..14a97af152 --- /dev/null +++ b/packages/react-native-web/src/exports/useColorScheme/__tests__/index-test.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import * as React from 'react'; +import { render } from '@testing-library/react'; +import Appearance from '../../Appearance'; +import useColorScheme from '..'; + +describe('useColorScheme', () => { + test('keeps its subscription active across rerenders', () => { + const remove = jest.fn(); + const addChangeListener = jest + .spyOn(Appearance, 'addChangeListener') + .mockReturnValue({ remove }); + + function Component({ label }): React.Node { + const colorScheme = useColorScheme(); + return
{`${label}:${colorScheme}`}
; + } + + const { rerender, unmount } = render(); + expect(addChangeListener).toHaveBeenCalledTimes(1); + expect(remove).not.toHaveBeenCalled(); + + rerender(); + expect(addChangeListener).toHaveBeenCalledTimes(1); + expect(remove).not.toHaveBeenCalled(); + + unmount(); + expect(remove).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/react-native-web/src/exports/useColorScheme/index.js b/packages/react-native-web/src/exports/useColorScheme/index.js index a2970115d3..5f08bdb116 100644 --- a/packages/react-native-web/src/exports/useColorScheme/index.js +++ b/packages/react-native-web/src/exports/useColorScheme/index.js @@ -25,7 +25,7 @@ export default function useColorScheme(): ColorSchemeName { } const { remove } = Appearance.addChangeListener(listener); return remove; - }); + }, []); return colorScheme; }