fix theme cross-tab write loop (#2774)

* don't write on onUpdate, memoize

* refac useColorModeTheme
zio/stable
Hailey 2024-02-06 21:16:50 -08:00 committed by GitHub
parent dc6603a1b9
commit 573cf31d86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 37 deletions

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import {useColorScheme} from 'react-native' import {ColorSchemeName, useColorScheme} from 'react-native'
import {useThemePrefs} from 'state/shell' import {useThemePrefs} from 'state/shell'
import {isWeb} from 'platform/detection' import {isWeb} from 'platform/detection'
@ -10,21 +10,31 @@ export function useColorModeTheme(): ThemeName {
const colorScheme = useColorScheme() const colorScheme = useColorScheme()
const {colorMode, darkTheme} = useThemePrefs() const {colorMode, darkTheme} = useThemePrefs()
return React.useMemo(() => { React.useLayoutEffect(() => {
if ( const theme = getThemeName(colorScheme, colorMode, darkTheme)
(colorMode === 'system' && colorScheme === 'light') || updateDocument(theme)
colorMode === 'light' updateSystemBackground(theme)
) { }, [colorMode, colorScheme, darkTheme])
updateDocument('light')
updateSystemBackground('light') return React.useMemo(
return 'light' () => getThemeName(colorScheme, colorMode, darkTheme),
} else { [colorScheme, colorMode, darkTheme],
const themeName = darkTheme ?? 'dim' )
updateDocument(themeName) }
updateSystemBackground(themeName)
return themeName function getThemeName(
} colorScheme: ColorSchemeName,
}, [colorMode, darkTheme, colorScheme]) colorMode: 'system' | 'light' | 'dark',
darkTheme?: ThemeName,
) {
if (
(colorMode === 'system' && colorScheme === 'light') ||
colorMode === 'light'
) {
return 'light'
} else {
return darkTheme ?? 'dim'
}
} }
function updateDocument(theme: ThemeName) { function updateDocument(theme: ThemeName) {

View File

@ -20,36 +20,38 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const [colorMode, setColorMode] = React.useState(persisted.get('colorMode')) const [colorMode, setColorMode] = React.useState(persisted.get('colorMode'))
const [darkTheme, setDarkTheme] = React.useState(persisted.get('darkTheme')) const [darkTheme, setDarkTheme] = React.useState(persisted.get('darkTheme'))
const setColorModeWrapped = React.useCallback( const stateContextValue = React.useMemo(
(_colorMode: persisted.Schema['colorMode']) => { () => ({
setColorMode(_colorMode) colorMode,
persisted.write('colorMode', _colorMode) darkTheme,
}, }),
[setColorMode], [colorMode, darkTheme],
) )
const setDarkThemeWrapped = React.useCallback( const setContextValue = React.useMemo(
(_darkTheme: persisted.Schema['darkTheme']) => { () => ({
setDarkTheme(_darkTheme) setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
persisted.write('darkTheme', _darkTheme) setColorMode(_colorMode)
}, persisted.write('colorMode', _colorMode)
[setDarkTheme], },
setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
setDarkTheme(_darkTheme)
persisted.write('darkTheme', _darkTheme)
},
}),
[],
) )
React.useEffect(() => { React.useEffect(() => {
return persisted.onUpdate(() => { return persisted.onUpdate(() => {
setColorModeWrapped(persisted.get('colorMode')) setColorMode(persisted.get('colorMode'))
setDarkThemeWrapped(persisted.get('darkTheme')) setDarkTheme(persisted.get('darkTheme'))
}) })
}, [setColorModeWrapped, setDarkThemeWrapped]) }, [])
return ( return (
<stateContext.Provider value={{colorMode, darkTheme}}> <stateContext.Provider value={stateContextValue}>
<setContext.Provider <setContext.Provider value={setContextValue}>
value={{
setDarkTheme: setDarkThemeWrapped,
setColorMode: setColorModeWrapped,
}}>
{children} {children}
</setContext.Provider> </setContext.Provider>
</stateContext.Provider> </stateContext.Provider>