diff --git a/lib/hooks/theme.js b/lib/hooks/theme.js new file mode 100644 index 000000000..e69176c9c --- /dev/null +++ b/lib/hooks/theme.js @@ -0,0 +1,37 @@ +// @flow + +import * as React from 'react'; +import { useDispatch } from 'react-redux'; + +import { updateThemeInfoActionType } from '../actions/theme-actions.js'; +import type { Shape } from '../types/core.js'; +import type { GlobalTheme, GlobalThemeInfo } from '../types/theme-types.js'; +import { useSelector } from '../utils/redux-utils.js'; + +function useUpdateSystemTheme(): (colorScheme: ?GlobalTheme) => mixed { + const globalThemeInfo = useSelector(state => state.globalThemeInfo); + const dispatch = useDispatch(); + + return React.useCallback( + (colorScheme: ?GlobalTheme) => { + if (globalThemeInfo.systemTheme === colorScheme) { + return; + } + + let updateObject: Shape = { + systemTheme: colorScheme, + }; + if (globalThemeInfo.preference === 'system') { + updateObject = { ...updateObject, activeTheme: colorScheme }; + } + + dispatch({ + type: updateThemeInfoActionType, + payload: updateObject, + }); + }, + [globalThemeInfo, dispatch], + ); +} + +export { useUpdateSystemTheme }; diff --git a/native/themes/theme-handler.react.js b/native/themes/theme-handler.react.js index 2c9c34353..346622a58 100644 --- a/native/themes/theme-handler.react.js +++ b/native/themes/theme-handler.react.js @@ -1,65 +1,42 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { Appearance } from 'react-native'; -import { useDispatch } from 'react-redux'; -import { updateThemeInfoActionType } from 'lib/actions/theme-actions.js'; -import type { Shape } from 'lib/types/core.js'; -import type { GlobalTheme, GlobalThemeInfo } from 'lib/types/theme-types.js'; +import { useUpdateSystemTheme } from 'lib/hooks/theme.js'; -import { useSelector } from '../redux/redux-utils.js'; import { osCanTheme } from '../themes/theme-utils.js'; function ThemeHandler(): null { - const globalThemeInfo = useSelector(state => state.globalThemeInfo); - const dispatch = useDispatch(); - const updateSystemTheme = React.useCallback( - (colorScheme: ?GlobalTheme) => { - if (globalThemeInfo.systemTheme === colorScheme) { - return; - } - - let updateObject: Shape = { - systemTheme: colorScheme, - }; - if (globalThemeInfo.preference === 'system') { - updateObject = { ...updateObject, activeTheme: colorScheme }; - } - - dispatch({ - type: updateThemeInfoActionType, - payload: updateObject, - }); - }, - [globalThemeInfo, dispatch], - ); + const updateSystemTheme = useUpdateSystemTheme(); React.useEffect(() => { if (!osCanTheme) { return undefined; } const subscription = Appearance.addChangeListener(({ colorScheme }) => { invariant( colorScheme === undefined || colorScheme === null || colorScheme === 'light' || colorScheme === 'dark', 'Flow types for Appearance module are non-specific', ); updateSystemTheme(colorScheme); }); return () => subscription.remove(); }, [updateSystemTheme]); React.useEffect( - () => updateSystemTheme(Appearance.getColorScheme()), + () => { + updateSystemTheme(Appearance.getColorScheme()); + }, // eslint-disable-next-line react-hooks/exhaustive-deps [], ); return null; } export default ThemeHandler;