Search code examples
react-nativereact-hooksreact-native-flatlistasyncstorage

IS there any Way To store response received from APISAUCE API into the Async Storage as cache and show it in Flat List in React Native


I am Getting Response From Node Server using APISAUCE and then showing the Data in FlatList . What I Actually Want To Do is Store This Response in AsyncStorage as Cache so when app is offline data to be Shown in FlatList must be retrieved from AsyncStorage Instead of Fetching it From Server.

This is My Code Implementation :

 import { create } from "apisauce";

const apiClient = create({
    baseURL : "http://192.168.10.9:9000/api"

    });



    export default apiClient;
import apiClient from "./client";

    
const endpoint = "/listings";

const getListings =() =>{

    return apiClient.get(endpoint);
}

export default {getListings};
import React , { useState } from "react";

export default useAPI=(API)=> 
{
 const[data,setData]=useState([]);
 const [error , setError]=useState(false);
 const [isLoading ,setLoading]=useState();


 
const request = async()=> {
    setLoading(true);
    const response = await API();
    setLoading(false);
    if(!response.ok) return setError(true);
 
 
     setError(false);
     setData(response.data);
     
    
 }

 return {error , data ,isLoading ,request  }

}


function ListingScreen({navigation}) {

  const loadListing= useAPI(getListings.getListings);
 

useEffect(()=>{

loadListing.request();

}, []);


    return (
        <View style={styles.container} >
{loadListing.error && (
    <View style={{marginTop:60}}>
        <Text style={{textAlign:"center"}}>
            Cannot Retrieve Data From Server
        </Text>

        <AppButton title="retry" onPress={loadListing.request} />
    </View>
)}

{loadListing.isLoading ?  <View>
    
            <ActivityIndicator animating={true} size={80} color="grey" />
         </View>  : 

       <FlatList data={loadListing.data} keyExtractor={list=>list.id.toString()}
        
        renderItem ={({item}) => <Card title={item.title} subtitle={"$" +item.price} 
        image={item.images[0].url} onPress={()=>navigation.navigate("ListingDetails" ,item )}  />

    } />
}

</View>
    );

}

Solution

  • When user open the app:

    • first checking local storage
    • if data exist on there , parse data and then render data to your flatlist.
    • if was not found so request to the your url then convert data to string and store in storage. At the end update your data.
    import React , { useState } from "react";
    
    export default useAPI=(URL)=> 
    {
     const[data,setData]=useState([]);
     const [error , setError]=useState(false);
     const [isLoading ,setLoading]=useState();
    
    const _getDataFromStorage = async () => {
      /*
      - Getting data from async storage
      - If data wasn't null, Parse data for covering string to object 
      and update your states and return true
      - If data was null return false*/
    }
     
    const request = async ()=> {
       try {
        if (await _getDataFromStorage()) {
          return;
        }
    
        setLoading(true);
        const response = await fetch(
          URL,
          //your request options
        );
        setLoading(false);
        if(!response.ok) 
          return setError(true);
        
        const responseJson = await response.json();
        setError(false);
        setData(responseJson.data);
       } catch (error) {
         console.error(error);
         setError(true);
       }
        
     }
    
     return {error , data ,isLoading}
    }
    

    and do your other implementations.