Search code examples
javascriptreact-nativeasyncstorage

How can I store a text field permanently in react native?


Sorry if this is a fairly basic question, I am new to react native and mobile development in general.

I have recently begun building a mobile application using expo and react native, but I have run into an issue in doing so. What I am trying to accomplish is to build a page where users can edit profile details that are not required to be stored in the backend. I need these text fields to save permanently until they are potentially edited at a later time by the user.

Initially, it seemed that using AsyncStorage would be the way to go about this, however, I discovered that upon closing the expo server and restarting it, the text is deleted and replaced with the placeholders. Does this mean that I improperly set up AsyncStorage, or is this simply the nature of expo? Would this data save permanently if the app in question were actually exported and deployed? I considered using something like realm instead, but it appears that this is not compatible with expo.

Any guidance on the best way to approach this problem would be appreciated. Again, sorry if the answer to this is obvious, I tried searching for information about this but found very little.


Solution

  • You're on the right path here, I use AsyncStorage for the same reason you do and it should be able get your data after the expo server restarts. I believe in your case you're using:

    AsyncStorage.setItem("exampleData")
    

    And in order to retrieve that exampleData again you have to use:

    AsyncStorage.getItem("exampleData")
    

    And store that exampleData into your redux. (I'm assuming you're using redux, but if you're not let me know!)


    You can also implement this in a screen setup so the first screen of your app retrieves that AsyncStorage data. I'll give you an example of how my code works.

    Here I have my navigation set up as:

    const MainNavigator = createSwitchNavigator({
      Startup: StartupScreen, // <-- This is the screen that gets the item
      StartAuth: StartSignup,
      Intro: IntroStack,
      Project: FullAppNavigator,
    });
    

    And the StartUpScreen as:

    import React, { useEffect } from "react";
    import { View, StyleSheet, ActivityIndicator } from "react-native";
    import AsyncStorage from "@react-native-async-storage/async-storage";
    import { useDispatch } from "react-redux";
    import { authenticate, logout } from "../store/actions/auth";
    import { getUserData } from "../store/actions/user";
    
    const StartupScreen = (props) => {
      const dispatch = useDispatch();
      useEffect(() => {
        const tryLogin = async () => {
          const userData = await AsyncStorage.getItem("exampleData"); // <-- here
          if (!userData) {
            props.navigation.navigate("StartAuth");
            return;
          }
          const transformedData = JSON.parse(userData);
          const { localId, token, introing } = transformedData;
    
          if (!token || !localId) {
            props.navigation.navigate("StartAuth");
            return;
          }
    
          if (introing) {
            await dispatch(getUserData());
            await dispatch(authenticate(localId, token));
            await props.navigation.navigate("Intro");
          } else {
            await dispatch(getUserData());
            await dispatch(authenticate(localId, token));
            await props.navigation.navigate("Project");
          }
        };
    
        tryLogin();
      }, [dispatch]);
    
      return (
        <View style={styles.screen}>
          <ActivityIndicator size="large" color="white" />
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      screen: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
      },
    });
    
    export default StartupScreen;
    

    So as you can see it gets the item from await AsyncStorage.getItem("exampleData") and then navigates to the next screen once it retrieves that item. In my case it receives a token, and when it receives that token it gets another item from the action getUserData, then navigates.

    Going this route also allows you to implement a loading screen as you retrieve that data from AsyncStorage, as you can see with the ActivityIndicator in that StartupScreen.