2015-11-05 2 views
25

Я использую AsyncStorage в ComponentWillMount, чтобы получить локально сохраненный accessToken, но он возвращает обещание после выполнения функции render(). Как я могу сделать render() до тех пор, пока обещание не будет завершено? Спасибо.React Native AsyncStorage извлекает данные после рендеринга

+1

Что именно вы пытаетесь сделать с данными? Один из способов обойти это - сохранить пустую переменную в функции getInitalState, а затем, когда AsyncStorage вернет значение, установите состояние с новым значением. –

+0

Спасибо за вопрос, я получаю локально сохраненный доступ к Token из AsyncStorage, чтобы установить состояние. Но поскольку он возвращает обещание, функция render() запускается сначала, тогда состояние устанавливается сразу после. Поэтому я вижу страницу входа в систему (~ 0,1 с) каждый раз, когда я посещаю приложение, так как render() проверяет состояние и возвращает страницу входа в систему или основное приложение. – skleest

+1

О, хорошо. Не знаете, как это исправить, кроме как, возможно, показывать сообщение загрузчика/загрузки, а затем заменить его либо именем входа, либо зарегистрированным в представлении. –

ответ

43

Вы не можете сделать render ждать, насколько я знаю. То, что я сделал в приложении, над которым я работаю, - это добавить экран загрузки, пока это обещание от AsyncStorage не будет устранено. Смотрите пример ниже:

import React, { 
    AsyncStorage, 
    View, 
    Text 
} from 'react-native'; 

class Screen extends React.Component { 

    state = { 
    isLoading: true 
    }; 

    componentDidMount() { 
    AsyncStorage.getItem('accessToken').then((token) => { 
     this.setState({ 
     isLoading: false 
     }); 
    }); 
    }, 

    render() { 
    if (this.state.isLoading) { 
     return <View><Text>Loading...</Text></View>; 
    } 
    // this is the content you want to show after the promise has resolved 
    return <View/>; 
    } 

} 

isLoading Установка недвижимости на государственном объекте вызовет повторную визуализацию, а затем вы можете показать содержимое, которое опирается на маркере доступа.

На боковой ноте я написал небольшую библиотеку под названием react-native-simple-store, которая упрощает управление данными в AsyncStorage. Надеюсь, вы найдете ее полезной.

+4

Это все еще работает в последней версии React Native? Я точно реализовал этот код, но он просто застрял на «Загрузка ...» навсегда. Если я запускаю консольный журнал рендера для отображения isLoading (без метода if), он возвращает false, а затем true, поэтому теоретически он должен работать. Но с помощью метода if он застрял на «Загрузка» навсегда, и журнал только возвращает false. – Hasen

+0

У меня такая же проблема, как у Хасена выше. Моя функция render() никогда не вызывается во второй раз после обновления состояния. Таким образом, мой экран загрузки просто показывает неопределенно .... – Dygerati

+0

У меня была такая же проблема, я продолжал застревать на экране загрузки. Кто-нибудь получил способ решить это? – DsEsteban

-3

React-native основан на Javascript, который не поддерживает блокирующие функции. Также это имеет смысл, поскольку мы не хотим, чтобы пользовательский интерфейс застревал или казался невосприимчивым. Что вы можете сделать, это обработать это в функции рендеринга. У меня есть экран загрузки, повторно отображающий его, когда вы получаете информацию от AsyncStorage

+1

Обновление переменной состояния будет «повторно отображать», что означает, что она снова вызовет функцию рендеринга. –

5

на основе реакции нативным doc, вы можете сделать что-то вроде этого:

import React, { Component } from 'react'; 
import { 
    View, 
} from 'react-native'; 

let STORAGE_KEY = '@AsyncStorageExample:key'; 

export default class MyApp extends Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     loaded: 'false', 
    }; 
    } 

    _setValue = async() => { 
    try { 
     await AsyncStorage.setItem(STORAGE_KEY, 'true'); 
    } catch (error) { // log the error 
    } 
    }; 

    _loadInitialState = async() => { 
    try { 
     let value = await AsyncStorage.getItem(STORAGE_KEY); 
     if (value === 'true'){ 
     this.setState({loaded: 'true'}); 
     } else { 
     this.setState({loaded: 'false'}); 
     this._setValue(); 
     } 
    } catch (error) { 
     this.setState({loaded: 'false'}); 
     this._setValue(); 
    } 
    }; 

    componentWillMount() { 
    this._loadInitialState().done(); 
    } 

    render() { 
    if (this.state.loaded === 'false') { 
     return (
     <View><Text>Loading...</Text></View> 
    ); 
    } 
    return (
     <View><Text>Main Page</Text></View> 
    ); 
    } 
} 
Смежные вопросы