Home > front end >  React Native - Type Script: How to save dark mode toggle state even after turning off the applicatio
React Native - Type Script: How to save dark mode toggle state even after turning off the applicatio

Time:08-24

What is the correct way so that I can save the dark mode switch even after turning off the application? I want to use the use-state-persist library to achieve the goal. In my example I show app.tsx , Preferences.tsx, ViewField.tsx . So that it will be possible to understand how the logic is built

DarkModeContext

import React from 'react';

interface DarkMode {
  isDarkMode: boolean;
  setDarkMode: () => void;
}
export const DarkModeContext = React.createContext<DarkMode>({} as DarkMode);

this is the app.tsx

import React, { useEffect, useState } from 'react';
import { syncStorage } from 'use-state-persist';

const App: () => ReactElement = () => {
  const [isDarkMode, setDarkMode] = useState(false);
const Drawer = createDrawerNavigator();
  const initStorage = async () => await syncStorage.init();

const toggleDarkMode = () => {
    setDarkMode(!isDarkMode);
  };

  return (
    <DarkModeContext.Provider value={{ isDarkMode, toggleDarkMode }}>
      <NavigationContainer>
        <Drawer.Navigator
          drawerContent={SideMenu}
          screenOptions={{
            drawerPosition: 'right',
            headerShown: false,
            drawerType: 'front',
          }}
        >
          <Drawer.Screen name='HomeScreen' component={StackNavigator} />
        </Drawer.Navigator>
      </NavigationContainer>
    </DarkModeContext.Provider>
  );
};
export default App;

this is the Preferences.tsx

import React, { useContext, useState } from 'react';
import ViewField from './ViewField';
import { DarkModeContext } from '~/context/DarkModeContext';
const Preferences = () => {
  const { isDarkMode, toggleDarkMode } = useContext(DarkModeContext);

 return (
      <View>
 <ViewField title='dark mode' isEnabled={isDarkMode} setValue={toggleDarkMode} />
</View>
  );
};

export default Preferences;

this is the ViewField.tsx

import { View, Text, Switch } from 'react-native';
import React from 'react';
import styles from './ViewFieldStyles';
import { useContext } from 'react';
import { DarkModeContext } from '~/context/DarkModeContext';

type Props = {
  title: string;
  isEnabled: boolean;
  setValue: () => void;
};
const ViewField = ({ title, isEnabled, setValue }: Props) => {
  const { isDarkMode } = useContext(DarkModeContext);

 return (
    <View style={isDarkMode ? styles.optionViewDark : styles.optionView}>
      <View style={styles.sameRowTextView}>
        <Text style={isDarkMode ? styles.optionTextDark : styles.optionText}>{title}</Text>
        <View style={styles.switchView}>
          <Switch
            trackColor={
              isDarkMode
                ? { false: 'rgba(255, 255, 255, 0.38)', true: 'rgba(187, 134, 252, 0.38)' }
                : { false: '#767577', true: 'rgba(4, 76, 163, 0.38)' }
            }
onValueChange={setValue}
            value={isEnabled}
          />
        </View>
      </View>
    </View>
  );
};

export default ViewField;

CodePudding user response:

Keep in mind that there seems to be some problems in use-state-persist using Boolean values. Furthermore, the latest published version of this library is from 2020.

However, the use-state-persist library just seems to be a wrapper around AsyncStorage, which is very well maintained. I would encourage you to use this library instead.

In your case, this could be implemented as follows:

  • Store the actual setter of the state in the context,
  • Create an effect that accesses the async storage on mount of the application: if there exists a value for the corresponding key, set the state of the context, if not, then do nothing.
  • In the Preferences component, store a new state in the async storage as well.
const App: () => ReactElement = () => {
  const [isDarkMode, setDarkMode] = useState(false);

  const contextValue = React.useMemo(() => ({
      isDarkMode,
      setDarkMode
  }), [isDarkMode])

  React.useEffect(() => {
    const load = async () => {
        const value = await AsyncStorage.getItem('isDarkMode');
        if (value !== null) {
            setDarkMode(JSON.parse(value));
        }
    }
    load();
  }, [])


  return (
    <DarkModeContext.Provider value={contextValue}>

   ...
};

In the Preferences component, set the state and save it to the local storage.

const Preferences = () => {
   const { isDarkMode, setDarkMode } = useContext(DarkModeContext);

   async function toggle() {
     const newValue = JSON.stringify(!isDarkMode);
     await AsyncStorage.setItem('isDarkMode', newValue);
     setDarkMode(prev => !prev);
   }

   return (
      <View>
        <ViewField title='dark mode' isEnabled={isDarkMode} setValue={toggle} />
      </View>
   );
}
  • Related