Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6287

How to combine a global MobX store with local state in the component?

$
0
0

I have the next component:

const App = observer(({injector}: Props) => {  const preferences = injector.getPreferences().execute()  const themeStore = useLocalStore(() => ({    _theme:      preferences.theme === ETheme.DARK        ? CombinedDarkTheme        : CombinedDefaultTheme,    get theme(): ReactNativePaper.Theme & Theme {      return this._theme    },    set theme(value: ReactNativePaper.Theme & Theme) {      this._theme = value    },  }))  const onThemeChange = React.useCallback(() => {    const colorScheme = Appearance.getColorScheme()    themeStore.theme =      colorScheme === 'dark' ? CombinedDarkTheme : CombinedDefaultTheme  }, [themeStore])  React.useEffect(() => {    if (preferences.theme === ETheme.SYSTEM) {      const subscription = Appearance.addChangeListener(onThemeChange)      return subscription.remove    }  }, [onThemeChange, preferences.theme])  return (<PaperProvider theme={themeStore.theme}><NavigationContainer theme={themeStore.theme}>        // Some views</NavigationContainer></PaperProvider>  )})

Global MobX store:

export default class PreferencesGateway implements IPreferencesGateway {  _preferences: Preferences = {    theme: ETheme.LIGHT,    signedInUserId: null,  }  constructor(private _storage: IStorageGateway) {    makeObservable(this, {      _preferences: observable,      preferences: computed,      setPreferences: action,    })  }  get preferences(): Preferences {    return this._preferences  }  async setPreferences({    theme,    signedInUserId,  }: PreferencesUpdate): Promise<void> {    if (theme) this._preferences.theme = theme    if (signedInUserId !== undefined)      this._preferences.signedInUserId = signedInUserId    await this.savePersistData()  }  async loadPersistData(): Promise<Preferences> {    const prefs = await this._storage.get<Preferences>(STORAGE_KEY_PREFERENCES)    if (prefs) this._preferences = prefs    return this._preferences  }  async savePersistData(): Promise<void> {    await this._storage.set(STORAGE_KEY_PREFERENCES, this._preferences)  }}

I need to App listened MobX global store (preferences.theme), the ETheme definition is below:

enum ETheme {  DARK = 'DARK',  LIGHT = 'LIGHT',  SYSTEM = 'SYSTEM',}

When the user sets preference.theme to DARK or LIGHT, the app just follows a simple expression:

theme = preferences.theme === ETheme.DARK ? ETheme.DARK : ETheme.LIGHT

However, when user sets preference.theme to AUTO, the app has to subscribe on Appearance.addChangeListener() and follows a system theme.

Unfortunately, my solution doesn't work correctly and leads to multiple changes when the user sets AUTO. I am a noobie in React Native and MobX and can't get an error reason but seems these stores conflict. I've also tried useState instead of useLocalStore but it just led to infinite redrawing.

Screenshot

How to fix it?

P.S. I feel that I've written a some bul****, and it can be simplified also.


Viewing all articles
Browse latest Browse all 6287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>