Search code examples
androidreactjscachingreact-nativeredux

How to Cache API data using AsyncStorage React Native


Fairly new to React native and its concepts. I have been playing with RN for a while to create an application to fetch API data from

http://jsonplaceholder.typicode.com/photos

I have been looking into the documentation of AsyncStorage to implement how i can cache the API data so that upon terminating the application, it doesn't have to deal with fetching the data from web again and again, but wasn't successfully able to implement it.

It will be great if you can provide me help/suggestion based on it. I have included my source code for the 2 important files in my application, along with the a Test.js file with how i was trying to achieve.

import React, {Component} from 'react';
import { FlatList, View, Text, AsyncStorage, ActivityIndicator } from 'react-native';
import axios from 'axios';
import GalleryDetail from './GalleryDetail';

class GalleryList extends Component {

state = { photos: []};

componentDidMount() {
    axios.get('http://jsonplaceholder.typicode.com/photos')
    .then(response => this.setState({ photos: response.data }))
    .catch((error)=> console.warn("fetch Error: ", error));
}

getPhotos = async()=> {
    try {
        photos = await AsyncStorage.getItem('GalleryPhotos');
    }
    catch (error) {
        console.error(error);
    }
}

savePhotos(){
    AsyncStorage.setItem('GalleryPhotos', this.state.photos);
    console.log('works !');
}

renderPhoto = ({item})=> {
    return <GalleryDetail photo={item}/>
}

keyExtractor = (photo, index) => photo.id;

render () {

    if(!this.state.photos){
        return <ActivityIndicator/>;
    }

    return (
            <FlatList
                data = {this.state.photos}
                keyExtractor={this.keyExtractor}
                renderItem={this.renderPhoto}
            />
    );
}
}

export default GalleryList;

and GalleryDetail linked with GalleryList-

import React, {Component} from 'react';
import { Text, View, Image } from 'react-native';
 import Card from './Card';
 import CardSection from './CardSection';

const GalleryDetail = (props)=> {
     return (
        <Card>
            <CardSection style = {styles.headerContentStyle}>
                <Image
                    style={styles.thumbnailStyle}
                    source = {{ uri: props.photo.thumbnailUrl}}/>
                <Text style= {styles.textStyle}>{props.photo.title}    </Text>
            </CardSection>
        </Card>
    );
};

const styles = {
   headerContentStyle: {
       flexDirection: 'column',
       justifyContent: 'space-around'
   },

   thumbnailStyle: {
       height: 60,
       width: 60
   },

   textStyle: {
       fontSize: 12,
       //textAlign: 'right',
       flexDirection: 'row',
       justifyContent: 'flex-end',
       flex: 1,
       flexWrap: 'wrap',
       marginLeft: 5,
       marginRight: 5,
    }
    }

    export default GalleryDetail;

My method of trying was that- Upon launching the application, it will first look in asyncStorage, if it finds the data- it fetches from async otherwise going to the web,fetching and storing again for later use. I tried to implement somewhat like this in a separate file since i dint wanted to breakdown my already running app. The weird broken syntax is

State = {
        photos: []
    }

    componentDidMount() {

        // just a variable acting to fetch data from the stored keyvalue pair

        check = AsyncStorage.getItem("PhotosKey").then((response) => {
                     this.setState({"PhotosKey": response});
                      }).done();

        if(check) {
            console.log('Data was fetched!!!!!');
            check();
        }

        else {
            console.log("Data was not fetched!");

            var Data = axios.get('http://jsonplaceholder.typicode.com/photos').
            then(response => this.setState({ photos: response.data })).
            catch((error)=> console.warn("fetch Error: ", error));



        }
    }

Thanks in advance!


Solution

  • async componentDidMount() {
        const photoStorage = await AsyncStorage.getItem('GalleryPhotos')
        if(photoStorage) {
          try {
            const photoResp = await axios.get('http://jsonplaceholder.typicode.com/photos')
            const photoData = await JSON.stringify(photoResp.data)
            await AsyncStorage.setItem('GalleryPhotos', photoData);
          } catch(e) {
            console.warn("fetch Error: ", error)
         }
        .then(response => this.setState({ photos: response.data }))
       }
     }
    

    later

    getPhotos = async()=> {
      try {
          photos = JSON.parse(await AsyncStorage.getItem('GalleryPhotos'));
      }
      catch (error) {
        console.error(error);
      }
    }