mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix/simplify invariant for ColorSchemeName, align manual typedef (#53397)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53397 This is a runtime behaviour fix and an API change to `Appearance.setColorScheme`, motivated by a user report where providing `'unspecified'` (valid) to this function would trigger an incorrect invariant throw. Furthermore, there is already a [first party use](https://github.com/facebook/react-native/blob/aec35b896053d9372ccdaf67c939b2eb216d3455/packages/react-native/Libraries/Utilities/Appearance.js#L101) where we call `Appearance.setColorScheme('unspecified')`. **Changes** - `Appearance.d.ts` (current public API, manual types): Fix `ColorSchemeName` type to include `'unspecified'` value, and narrow to remove nullability — aligning with existing Flow source for this type in `NativeAppearance`. - `Appearance.js` (implementation): Fix the invariant throw by **removing it**, and instead narrowing the input type to non-nullable. Redundant work in `getState` and `getColorScheme` is removed. Changelog: [General][Breaking] `Appearance.setColorScheme` no longer accepts a nullable value Reviewed By: andrewdacenko Differential Revision: D80705652 fbshipit-source-id: cf221a33447606653050d471ca2d0347ab30db81
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b7e64bea29
commit
a4581ecd8b
@@ -9,7 +9,7 @@
|
||||
|
||||
import {NativeEventSubscription} from '../EventEmitter/RCTNativeAppEventEmitter';
|
||||
|
||||
type ColorSchemeName = 'light' | 'dark' | null | undefined;
|
||||
type ColorSchemeName = 'light' | 'dark' | 'unspecified';
|
||||
|
||||
export namespace Appearance {
|
||||
type AppearancePreferences = {
|
||||
@@ -26,7 +26,7 @@ export namespace Appearance {
|
||||
*
|
||||
* Example: `const colorScheme = Appearance.getColorScheme();`
|
||||
*/
|
||||
export function getColorScheme(): ColorSchemeName;
|
||||
export function getColorScheme(): ColorSchemeName | null | undefined;
|
||||
|
||||
/**
|
||||
* Set the color scheme preference. This is useful for overriding the default
|
||||
@@ -34,9 +34,7 @@ export namespace Appearance {
|
||||
* appearance of the system UI, only the appearance of the app.
|
||||
* Only available on iOS 13+ and Android 10+.
|
||||
*/
|
||||
export function setColorScheme(
|
||||
scheme: ColorSchemeName | null | undefined,
|
||||
): void;
|
||||
export function setColorScheme(scheme: ColorSchemeName): void;
|
||||
|
||||
/**
|
||||
* Add an event handler that is fired when appearance preferences change.
|
||||
|
||||
+5
-17
@@ -14,7 +14,6 @@ import typeof INativeAppearance from './NativeAppearance';
|
||||
|
||||
import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
|
||||
import EventEmitter from '../vendor/emitter/EventEmitter';
|
||||
import invariant from 'invariant';
|
||||
|
||||
export type {AppearancePreferences};
|
||||
|
||||
@@ -60,7 +59,7 @@ function getState(): $NonMaybeType<typeof lazyState> {
|
||||
appearanceChanged: [AppearancePreferences],
|
||||
}>(NativeAppearance).addListener('appearanceChanged', newAppearance => {
|
||||
state.appearance = {
|
||||
colorScheme: toColorScheme(newAppearance.colorScheme),
|
||||
colorScheme: newAppearance.colorScheme,
|
||||
};
|
||||
eventEmitter.emit('change', state.appearance);
|
||||
});
|
||||
@@ -83,7 +82,7 @@ export function getColorScheme(): ?ColorSchemeName {
|
||||
// Lazily initialize `state.appearance`. This should only
|
||||
// happen once because we never reassign a null value to it.
|
||||
state.appearance = {
|
||||
colorScheme: toColorScheme(NativeAppearance.getColorScheme()),
|
||||
colorScheme: NativeAppearance.getColorScheme(),
|
||||
};
|
||||
}
|
||||
colorScheme = state.appearance.colorScheme;
|
||||
@@ -94,13 +93,13 @@ export function getColorScheme(): ?ColorSchemeName {
|
||||
/**
|
||||
* Updates the current color scheme to the supplied value.
|
||||
*/
|
||||
export function setColorScheme(colorScheme: ?ColorSchemeName): void {
|
||||
export function setColorScheme(colorScheme: ColorSchemeName): void {
|
||||
const state = getState();
|
||||
const {NativeAppearance} = state;
|
||||
if (NativeAppearance != null) {
|
||||
NativeAppearance.setColorScheme(colorScheme ?? 'unspecified');
|
||||
NativeAppearance.setColorScheme(colorScheme);
|
||||
state.appearance = {
|
||||
colorScheme: toColorScheme(NativeAppearance.getColorScheme()),
|
||||
colorScheme,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -114,14 +113,3 @@ export function addChangeListener(
|
||||
const {eventEmitter} = getState();
|
||||
return eventEmitter.addListener('change', listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
|
||||
*/
|
||||
function toColorScheme(colorScheme: ?string): ?ColorSchemeName {
|
||||
invariant(
|
||||
colorScheme === 'dark' || colorScheme === 'light' || colorScheme == null,
|
||||
"Unrecognized color scheme. Did you mean 'dark', 'light' or null?",
|
||||
);
|
||||
return colorScheme;
|
||||
}
|
||||
|
||||
+3
-5
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<b43428758b3aefd30b2bd8a32ec0878a>>
|
||||
* @generated SignedSource<<0170bc4ced1f6d3d4092d837027cd391>>
|
||||
*
|
||||
* This file was generated by scripts/js-api/build-types/index.js.
|
||||
*/
|
||||
@@ -4642,9 +4642,7 @@ declare type Separators = {
|
||||
updateProps: (select: "leading" | "trailing", newProps: Object) => void
|
||||
}
|
||||
declare type sequence = typeof sequence
|
||||
declare function setColorScheme(
|
||||
colorScheme: ColorSchemeName | null | undefined,
|
||||
): void
|
||||
declare function setColorScheme(colorScheme: ColorSchemeName): void
|
||||
declare function setComponentProviderInstrumentationHook(
|
||||
hook: ComponentProviderInstrumentationHook,
|
||||
): void
|
||||
@@ -5972,7 +5970,7 @@ export {
|
||||
AppState, // f7097b1b
|
||||
AppStateEvent, // 80f034c3
|
||||
AppStateStatus, // 447e5ef2
|
||||
Appearance, // b23e8105
|
||||
Appearance, // 00cbaa0a
|
||||
AutoCapitalize, // c0e857a0
|
||||
BackHandler, // a9f9bad9
|
||||
BackPressEventName, // 4620fb76
|
||||
|
||||
@@ -136,7 +136,7 @@ const ColorShowcase = (props: {themeName: string}) => (
|
||||
|
||||
const ToggleNativeAppearance = () => {
|
||||
const [nativeColorScheme, setNativeColorScheme] =
|
||||
useState<ColorSchemeName | null>(null);
|
||||
useState<ColorSchemeName>('unspecified');
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -155,7 +155,10 @@ const ToggleNativeAppearance = () => {
|
||||
title="Set to dark"
|
||||
onPress={() => setNativeColorScheme('dark')}
|
||||
/>
|
||||
<Button title="Unset" onPress={() => setNativeColorScheme(null)} />
|
||||
<Button
|
||||
title="Unset"
|
||||
onPress={() => setNativeColorScheme('unspecified')}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user