diff --git a/Libraries/Utilities/Appearance.js b/Libraries/Utilities/Appearance.js index e6a4f9b7849..1d633fef098 100644 --- a/Libraries/Utilities/Appearance.js +++ b/Libraries/Utilities/Appearance.js @@ -8,7 +8,9 @@ * @flow strict-local */ -import EventEmitter from '../vendor/emitter/EventEmitter'; +import EventEmitter, { + type EventSubscription, +} from '../vendor/emitter/EventEmitter'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import NativeAppearance, { type AppearancePreferences, @@ -78,16 +80,19 @@ module.exports = { ); return nativeColorScheme; }, + /** * Add an event handler that is fired when appearance preferences change. */ - addChangeListener(listener: AppearanceListener): void { - eventEmitter.addListener('change', listener); + addChangeListener(listener: AppearanceListener): EventSubscription { + return eventEmitter.addListener('change', listener); }, + /** - * Remove an event handler. + * @deprecated Use `remove` on the EventSubscription from `addEventListener`. */ removeChangeListener(listener: AppearanceListener): void { + // NOTE: This will report a deprecation notice via `console.error`. eventEmitter.removeListener('change', listener); }, }; diff --git a/Libraries/Utilities/useColorScheme.js b/Libraries/Utilities/useColorScheme.js index 2712a846e58..2c7ffa5d29b 100644 --- a/Libraries/Utilities/useColorScheme.js +++ b/Libraries/Utilities/useColorScheme.js @@ -18,8 +18,10 @@ export default function useColorScheme(): ?ColorSchemeName { () => ({ getCurrentValue: () => Appearance.getColorScheme(), subscribe: callback => { - Appearance.addChangeListener(callback); - return () => Appearance.removeChangeListener(callback); + const appearanceSubscription = Appearance.addChangeListener(callback); + return () => { + appearanceSubscription.remove(); + }; }, }), [], diff --git a/packages/rn-tester/js/examples/Appearance/AppearanceExample.js b/packages/rn-tester/js/examples/Appearance/AppearanceExample.js index c7cc76fec7e..55b38f03346 100644 --- a/packages/rn-tester/js/examples/Appearance/AppearanceExample.js +++ b/packages/rn-tester/js/examples/Appearance/AppearanceExample.js @@ -11,29 +11,32 @@ import * as React from 'react'; import {Appearance, Text, useColorScheme, View} from 'react-native'; import type {AppearancePreferences} from 'react-native/Libraries/Utilities/NativeAppearance'; +import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; import {RNTesterThemeContext, themes} from '../../components/RNTesterTheme'; class ColorSchemeSubscription extends React.Component< {...}, {colorScheme: ?string, ...}, > { + _subscription: ?EventSubscription; + state = { colorScheme: Appearance.getColorScheme(), }; componentDidMount() { - Appearance.addChangeListener(this._handleAppearanceChange); + this._subscription = Appearance.addChangeListener( + (preferences: AppearancePreferences) => { + const {colorScheme} = preferences; + this.setState({colorScheme}); + }, + ); } componentWillUnmount() { - Appearance.removeChangeListener(this._handleAppearanceChange); + this._subscription?.remove(); } - _handleAppearanceChange = (preferences: AppearancePreferences) => { - const {colorScheme} = preferences; - this.setState({colorScheme}); - }; - render() { return (