2017-12-31 129 views
0

ネイティブとその概念にかなり新しい。私は私が実装するAsyncStorageのドキュメントに探してきたAsyncStorage React Nativeを使用してAPIデータをキャッシュする方法

http://jsonplaceholder.typicode.com/photos

からのAPIデータをフェッチするアプリケーションを作成するために、しばらくの間、RNで遊んでてきましたどのようにAPIデータをキャッシュすることができるので、アプリケーション終了時に何度もWebからデータを取得する必要はありませんが、実装に成功できませんでした。

それに基づいて助けてくれると助かります。私のアプリケーションに2つの重要なファイルのソースコードを、Test.jsファイルと一緒に、私が達成しようとしていたものと一緒に含めました。 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; 

にしようとする私の方法をリンクさ

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; 

とGalleryDetailそれが非同期からフェッチデータ - を見つけた場合は、アプリケーションを起動すると、それは最初に、asyncStorageになりますthat- ましたさもなければウェブに行き、後で使用するために再び取り出して保管してください。 私はすでに実行中のアプリケーションを細かくしたいので、別のファイルにこのように実装しようとしました。奇妙な壊れた構文は

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



     } 
    } 

ありがとうございます!

答えて

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

後でSubramanyaから

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

ありがとう@Subramanyaあなたの助けになりました。それは私のコードがどのように見えるかの本当に良い認識を私に与えました。私は分かち合う心配がほとんどありません。 Reactネイティブの中にasyncstorageを追加しようとする私の動機は、アプリケーションの起動時に、見つけられなかった場合はGalleryPhotosからデータをフェッチする必要があります。データをフェッチし、次に使用するために保存します。あなたが書いたコードは、毎回同じようにデータを取り出して保存することです。データは毎回同じなので、毎回フェッチする必要はありません。私が何かを見逃している場合は、私を修正してください:) –

+1

@ Rex-ありがとうございました。私は、Reduxを実装した後にアプリケーションを更新する際に、このコードを完全に調べます。しかし、お時間をいただければ幸いです。 –

+0

私はあなたのコメントに基づいて答えを更新しました、私は条件付きでチェックを追加しました.GalleryPhotosが存在するかどうかにかかわらず、API呼び出しを行います、それが助けてくれることを願っています。 –

1

アプローチは基本的にあなたが始めるために必要なすべてのですが、私はちょうどあなたのアプリが成長したときに、あなたは間違いなく理解することができる場所redux-persistと状態管理のアプローチを紹介するつもりです。

は、実行しやすく、実装しやすく、拡張が容易です。

レッツは、あなたのアプリがreduxとフックアップし、かなり組織的状態の木、redux-persist店舗AsyncStorageとアプリケーション全体の状態やお好みの任意のストレージエンジンを実装していると言います。

たとえば、APIエンドポイントで写真のコレクションが返され、店舗を更新するだけで、ユーザーはデータが安全であり、redux-persistで保存されると期待できると仮定します。

私は

以下のすべてのコードをテストしていないのは、あなたのアプリケーションのエントリポイントでstoreまず、

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; 

最後
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> 
    ); 
    } 
} 

を定義してみましょう、あなたのAPIのロジック。

// 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; 
    } 
}; 

データを取得するには、Reduxのは、すべての余分なロジックを抽象化し、redux-persistが自動的にあなたのためにすでにあることないのでsetItem, getItemこれ以上はないことがわかります。あなたのプロジェクトでは、持続Reduxのをインストールし

  1. 、要約する

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

  2. persistStoreおよびautoRehydrateフォームをredux-persist形式でインポートします。
  3. あなたの店にautoRehydrateを追加してください。
  4. ストアをpersistStoreに渡します。
  5. あなたのレデューサーのpersist/REHYDRATEアクションを聞き、それに応じて状態を設定します。

私の回答が役に立ちます。

+0

私はすでにredux-persistを使用していますが、これは非常にクールですが、キャッシュの有効期限はどうですか? – Fryck

関連する問題