javascriptreactjsreact-nativeasync-awaitasyncstorage

How to load a useState with data from async-storage without null for react-native


I need to initialize my useState with the value from local storage. I can't get async-storage to stop making everything async. If i initialize with null or a random default then I get multiple re renders as the promises get fulfilled which causes other issues. I also tried useAsuncStorage which also only returns async functions. I have the same exact code written using cookies with react-cookie and useCookie and do not have any issues. Do you all have any suggestions?

import { useEffect, useState } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";

const usePostFilterOptions = () => {
    const getPostFilterType = async () => {
        const savedPostFilterType = await AsyncStorage.getItem('postFilterType') ?? 'trending';
        return savedPostFilterType;
    }

    const getPostModeType = async () => {
        const savedPostModeType = await AsyncStorage.getItem('postModeType') ?? 'home';
        return savedPostModeType;
    }

    const [postFilterType, setPostFilterType] = useState(getPostFilterType());
    const [postModeType, setPostModeType] = useState(getPostModeType());


    const updatePostFilterType = async (type) => {
        await AsyncStorage.setItem('postFilterType', type);
        setPostFilterType(type);
    }

    const updatePostModeType = async (type) => {
        await AsyncStorage.setItem('postModeType', type);
        setPostModeType(type);
    }

    return { postFilterType, updatePostFilterType, postModeType, updatePostModeType };
};

export default usePostFilterOptions;



Solution

  • Fetching data from localstore is just async. You can not make this sync. But you can add additional state like a prop isLoading or something like that. You can stop rendering or show a loading icon or whatever you like.

    const [postFilterType, setPostFilterType] = useState("trending");
    const [postModeType, setPostModeType] = useState("home");
    const [isLoading, setLoading] = useState(true);
    
    
    AsyncStorage.getItem('postFilterType').then(r => setPostFilterType(r));
    AsyncStorage.getItem('postModeType').then(r => setPostModeType(r));
    
    // your updateMethods
    
    return {
       isLoading, 
       postFilterType
       postModeType,
       updatePostFilterType,
       updatePostModeType 
    }
    

    In your component

    const {isLoading} = usePostFilterOptions();
    
    if (isLoading) {
       return <div>Loading...</div>;
       // or
       return;  // stop rendering the component, and wait until data is fetched.
    }
    
    // render component here