2017-12-31 242 views
0

네이티브 및 그 개념에 상당히 새로워졌습니다. 나는AsyncStorage를 사용하여 API 데이터를 캐시하는 방법 React 네이티브

http://jsonplaceholder.typicode.com/photos 내가 AsyncStorage의 문서로 찾고있다

하는 구현하는에서 API 데이터를 가져올 수있는 응용 프로그램을 만드는 동안 RN와 함께 연주 한 API 데이터를 캐시하여 애플리케이션을 종료 할 때 웹에서 데이터를 반복해서 가져올 필요가 없지만 성공적으로 구현할 수는 없었습니다.

나에게 도움/제안을 제공해 주시면 대단합니다. 내 응용 프로그램에있는 중요한 파일 2 개에 대한 소스 코드를 포함하여 Test.js 파일을 얻는 방법을 설명했습니다.

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

시도 내 방법은 그것이 비동기에서 페치 데이터 - 발견하면, 먼저, asyncStorage에서 찾게됩니다 응용 프로그램을 실행하면 드리려고 했다 그렇지 않으면 웹으로 이동하여 나중에 사용하기 위해 다시 가져 와서 저장하십시오. 나는 이미 별개의 파일에 이것을 구현하려고 애썼다. 이상한 깨진 구문은

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

나중에

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

@Subramanya에게 감사드립니다. 그것은 내 코드가 어떻게 생겼는지에 대한 정말 좋은 인식을주었습니다. 나는 단지 공유 할 염려가 거의 없다. React 네이티브 내부에 asyncstorage를 추가하려는 동기는 응용 프로그램을 시작할 때 GalleryPhotos에서 데이터를 가져와야합니다. 찾을 수 없다면 데이터를 가져 와서 다음에 사용할 수 있도록 저장합니다. 귀하가 작성한 코드는 매번 데이터를 가져 오는 것과 비슷합니다. 데이터가 매번 같기 때문에 매번 가져올 필요가 없습니다. 내가 뭔가를 놓친다면 나를 바로 잡으세요. :) –

+1

@ 렉스 - 고마워요. Redux를 구현 한 후 애플리케이션을 업데이트 할 때이 코드를 자세히 살펴볼 것이다. 하지만 고맙습니다. 내 질문에 대답하는 데 시간이 많이 걸렸을 거라 믿는다. (너무 길다) –

+0

나는 당신의 코멘트에 기초하여 대답을 업데이트했다. 조건이 충족되면 GalleryPhotos의 존재 여부와 함께 점검을 추가했다. –

1

Subramanya에서 접근 방식은 기본적으로, 나는 당신이 확실히 인식 할 수있는 앱이 증가 할 때 redux-persist으로 상태 관리 방법을 소개하겠습니다을 시작하는 데 필요한 모든 것입니다 .

는 구현하기 쉽고 확장하기 쉽습니다.

하자하면 앱이 redux으로 엮은 AsyncStorage 또는 원하는 모든 스토리지 엔진 상당히 조직 상태 트리, redux-persist 저장 전체 응용 프로그램 상태를 구현 말한다.

예를 들어 API 끝점에서 사진 모음을 반환한다고 가정 해 보겠습니다. 스토어를 업데이트하면 사용자는 데이터가 안전하고 redux-persist으로 저장 될 것으로 기대할 수 있습니다.

나는 앱의 진입 점에서

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

,

아래의 모든 코드의이 store 처음으로 정의 할 수 있습니다 테스트하지 않았습니다 마지막으로, 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 때문에이됩니다. 당신이 프로젝트에

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

요약하면,

  1. 설치 REDUX-유지됩니다.
  2. persistStore 및 autoRehydrate 형식을 redux-persist 형식으로 가져옵니다.
  3. 저장소에 autoRehydrate를 추가하십시오.
  4. 스토어를 persistStore에 전달하십시오.
  5. 감속기의 지속/REHYDRATE 동작을 듣고 적절하게 상태를 채 웁니다.

희망 답변

+0

이미 redux-persist를 사용하고 있습니다. 매우 멋지지만 캐시 만료 시간은 어떻게됩니까? – Fryck