2017-12-31 128 views
0

Ziemlich neu zu reagieren native und seine Konzepte. Ich habe für eine Weile mit RN gespielt, eine Anwendung zu erstellen, holen API Daten ausSo cachen Sie API-Daten mit AsyncStorage Reagieren Sie auf Native

http://jsonplaceholder.typicode.com/photos

Ich habe in der Dokumentation von AsyncStorage suchen zu implementieren Wie kann ich die API-Daten zwischenspeichern, so dass es beim Beenden der Anwendung nicht immer wieder mit dem Abrufen der Daten aus dem Web zu tun hat, sondern es nicht erfolgreich implementieren konnte.

Es wird großartig sein, wenn Sie mir Hilfe/Vorschlag basierend darauf zur Verfügung stellen können. Ich habe meinen Quellcode für die 2 wichtigen Dateien in meiner Anwendung, zusammen mit der Test.js Datei mit, wie ich versucht habe, zu erreichen.

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; 

und GalleryDetail mit GalleryList- verknüpft

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; 

Meine Methode zu versuchen, war dass- Nach dem Start der Anwendung, wird es zuerst in asyncStorage aussehen, wenn es die Daten- findet es von Asynchron holt andernfalls ins Web gehen, holen und für spätere Verwendung wieder speichern. Ich habe versucht, so etwas in einer separaten Datei zu implementieren, da ich meine bereits laufende App nicht aufschlüsseln wollte. Die seltsame gebrochene Syntax ist

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)); 



     } 
    } 

Vielen Dank im Voraus!

Antwort

0
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 })) 
    } 
} 

später

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

Dank @Subramanya für Ihre Hilfe. Es hat mir eine wirklich gute Vorstellung davon gegeben, wie mein Code aussehen wird. Ich habe nur wenige Bedenken zu teilen. Mein Motiv, asyncstorage innerhalb von React native hinzuzufügen, ist so, dass es beim Start der Anwendung Daten von GalleryPhotos holen sollte, wenn es nicht in der Lage war, Daten zu finden und sie dann für die nächste Verwendung zu speichern. Der Code, den Sie geschrieben haben, ist meiner Meinung nach mehr wie das Abrufen und Speichern der Daten jedes Mal. Da die Daten immer gleich sind, müssen sie nicht jedes Mal abgerufen werden. Bitte korrigieren Sie mich, wenn ich etwas verpasse. :) –

+1

@ Rex - Vielen Dank für Ihren Code. Ich werde diesen Code bei der Aktualisierung meiner Anwendung nach der Implementierung von Redux vollständig untersuchen. Aber vielen Dank für deine Zeit. Ich glaube, es dauerte viel Zeit, um meine Frage zu beantworten (so lang sein) –

+0

Ich habe die Antwort basierend auf Ihrem Kommentar aktualisiert, fügte ich einen Haken mit ob Bedingung, ob GalleryPhotos existiert oder nicht und dann api Anruf machen, hoffe es hilft –

1

Der Ansatz von Subramanya ist im Grunde alles, was Sie anfangen müssen, ich werde einfach mit redux-persist einen Zustand Management-Ansatz einzuführen, in denen Sie auf jeden Fall zu schätzen wissen, wenn Ihre Anwendung wächst .

Redux Persist ist performant, einfach zu implementieren und einfach zu erweitern.

Lassen Sie sagen, Sie haben Ihre App mit redux angeschlossen und einen ziemlich organisierten Zustand Baum implementiert, redux-persist speichert die gesamte App-Status mit AsyncStorage oder einem Speicher-Engine Ihrer Wahl.

Angenommen, Ihr API-Endpunkt gibt eine Sammlung von Fotos zurück, Sie müssen lediglich den Store aktualisieren, und Ihre Benutzer können erwarten, dass ihre Daten sicher sind und unter redux-persist gespeichert werden.

Ich habe nicht alle der Code getestet unter

Lassen Sie uns die store zuerst definieren

import { AsyncStorage } from 'react-native'; 
import { createStore, compose, applyMiddleware, } from "redux"; 
import { persistStore } from "redux-persist"; 
import ReduxThunk from "redux-thunk"; 

import reducers from "../reducers" 

const middleWare = [ReduxThunk] 

const store = createStore(
    reducers, 
    {}, 
    compose(applyMiddleware(...middleWare)) 
) 

// you can define more parameters, like blacklist or whitelist a reducer 
// also, specify storage engine 
persistStore(store, { storage: AsyncStorage }); 

export default store; 

Zu Ihrer App Einstiegspunkt,

import React, { Component } from "react"; 
import { Provider } from "react-redux"; 
import Router from "./Router"; 
import store from './store'; 

export default class App extends Component { 

    constructor(props) { 
    super(props); 
    } 

    render() { 
    return (
     <Provider store={store}> 
     <Router /> // navigator 
     </Provider> 
    ); 
    } 
} 

Schließlich API-Logik.

// action creator 
export storePhoto = photos => { 
    return { 
     type: 'STORE_PHOTOS', 
     payload: photos 
    } 
} 

// photos reducer 
import { REHYDRATE } from 'redux-persist/constants'; 

export default (state = {}, action) => { 
    switch (action.type) { 
    case STORE_PHOTOS: 
     return { ...state, photos: action.payload } 
    // this is where `redux-persist` handles caching 
    case REHYDRATE: 
     var incoming = action.payload; 
     if(incoming) return { ...state, ...incoming } 
     return state; 
    default: 
     return state; 
    } 
}; 

Daten abrufen, werden Sie, dass redux sehen die überschüssigen Logiken alle abstrahiert und es gibt nicht mehr setItem, getItem weil redux-persist, dass für Ihre bereits automatisch der Fall ist.

import { connect } from "react-redux"; 
import { storePhotos } from "./actions"; 

class GalleryList extends Component { 

    async componentDidMount() { 
     const photos = await axios.get('http://jsonplaceholder.typicode.com/photos'); 
     storePhoto(photos) 
    } 

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

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

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

// pull data from photos reducer 
const mapStateToProps = ({ photos }) => { 
    return { 
     photos: photos.photos 
    } 
} 

export default connect(mapStateToProps, { storePhotos })(GalleryList); 

Zusammengefasst

  1. installieren redux-beharren Sie projizieren.
  2. Import persistStore und autoRehydrate Formular redux-persist.
  3. Fügen Sie autoRehydrat Ihrem Geschäft hinzu.
  4. Übergeben Sie Ihren Shop an persistStore.
  5. Hören Sie die Persist/REHYDRATE-Aktion auf Ihrem Reduzierer und bevölkern Sie den Status entsprechend.

Hope meine Antwort hilft!

+0

Ich verwende bereits Redox-Persist, es ist sehr cool, aber was ist mit Cache-Ablaufzeit? – Fryck

Verwandte Themen