React Native AsyncStorage Access on App Load

Viewed 623

I need to access data from AsycStorage to pass to one of my functions, WidgetGenerator, immediately when the app is opened. However, there doesn't seem to be a way to call getData() and wait for it to set the value of initVals, it just continues executing code sequentially in WidgetGenerator() and passes undefined to the component it returns because getData() hasn't returned yet. Also, it doesn't seem like react likes it when I make WidgetGenerator an async function. What do I do so that I will be able to access AsyncData on loading?

const getData = async () => {
        try {
            const jsonValue = await AsyncStorage.getItem('@1629349495937')
            if (jsonValue != null) {
                //console.log(JSON.parse(jsonValue));
                initVals = JSON.parse(jsonValue);
            }
        } catch(e) {
            // error reading value
        }
    }
    function WidgetGenerator(props) {
        
        switch (props.args[0]) {
            case "heading":
                return <UIComponents.UIHeading
                            text={props.args[1]}
                            id={props.id}
                            init={initVals ? initVals[props.id] : undefined}
                        />;
            case "checkbox":
                return <UIComponents.UICheckbox
                            text={props.args[1]}
                            id={props.id}
                            callback={props.callback}
                            init={initVals ? initVals[props.id] : undefined}
                        />;
        }
        
        return <View />;
    }
    
    return (
        <View>
            {widgetArray.map((data, index) => <WidgetGenerator key={index} id={index} args={data} callback={collectData}/>)}
            <UIComponents.UISubmitButton callback={submitData} />
        </View>
        
    );

}
1 Answers

There are some code pieces missing to give a full picture what's going on exactly, but I think I got it anyways. So you have to resolution strategies available:

  1. Use a sync storage solution, that can get you the data directly
  2. Get the data asynchronously, display a loading indicator or similar while loading

Use a sync storage solution

If you are able to install native dependencies you can install a library for sync data access like react-native-mmkv. Just go through its documentation, should be straightforward.

Load the data asynchronously

There are many ways to do it. Ideally, you load your app data once on the app start while showing a splash screen, and store the data in a global store (can be something as simple as a JS object), so you can access them directly during runtime. However, a general pattern for async data loading in react looks like this:

function Component() {
  const [data, setData] = useState();
  const [isError, setIsError] = useState(false);

  // load the data
  useEffect(() => {
    const asyncAction = async () => {
      try {
        const _data = await getData();
        setIsError(false);
        setData(data);
      } catch (e) {
        setIsError(true);
      }
    }
  }, []);

  if (isError) {
    return // view indicating an error
  }

  if (data == null) {
   return // view indicating loading
  }

  return <View>{/* actual implementation that is using data*/}</View>
}

There are many tutorials about this topic, that you can google.

Related