Используйте AsyncStorage для хранения токена в глобальном масштабе - PullRequest
0 голосов
/ 17 ноября 2018

Я изучаю реагирующий на родство с одной недели, и я чего-то не понимаю.

Вот что я делаю: я разрабатываю приложение, разбирающее Imgur API, мне как-то удалось через Webview проверить подлинностья и получил accessToken, refreshToken и т. д., которые я хранил локально в своем компоненте webview.

Теперь я хочу сохранить этот токен глобально в приложении, поэтому я провел некоторое исследование и обнаружил, что AsyncStorage (очевидно, небезопасен для хранения токеновно это нормально, это просто приложение для практики).

Итак, вот что я понял:

  • Вы даете ключ и значение через setItem, они как-то оборачивают его в Promise(Мне нужно немного изучить этот материал)
  • Затем вы можете вернуть его в другую асинхронную функцию.

Итак, вот что я сделал, чтобы установить свой элемент в моем компоненте входа в систему:

// login.js

    import React from 'react'
import {AsyncStorage, StyleSheet, WebView} from 'react-native'
import { StackActions, NavigationActions } from 'react-navigation';

const webviewRef = 'webview';
const CLIENT_ID = 'xxxxxxx';

class LoginImgur extends React.Component {
    accessToken : string;
    expiresIn : string;
    refreshToken : string;
    userName : string;

constructor(props) {
    super(props);
}

async storeItem(key, item) {
    try {
        let jsonOfItem = await AsyncStorage.setItem(key, JSON.stringify(item));
        return jsonOfItem;
    } catch (error) {
        console.log(error.message);
    }
}

_resetAction = StackActions.reset({
    index: 0,
    actions: [NavigationActions.navigate({ routeName: 'Index' })],
});

_changeNavigationState = async (webView) => {
   if (this._splitUrl(webView.url) === true) {
       console.log(this.accessToken);
       let json = this.storeItem('ACCESS_TOKEN', this.accessToken);
       this.props.navigation.dispatch(this._resetAction);
   }
};

_splitUrl(url : String) {
    if (url.search("access_token=") > 0) {
        let array = url.split("=");
            this.accessToken =   array[2].split('&')[0];
            this.expiresIn = array[3].split('&')[0];
            this.refreshToken =  array[5].split('&')[0];
            this.userName =  array[6].split('&')[0];
        return (true);
    }
    return (false);
}



webviewProps = {
    style: styles.webview_container,
    ref: webviewRef,
    javaScriptEnabled: true,
    onNavigationStateChange: this._changeNavigationState.bind(this),
    source: {
        uri: 'https://api.imgur.com/oauth2/authorize?client_id=' + CLIENT_ID + '&response_type=token&state=APPLICATION_STATE',
    }
};

render() {
    return (
        <WebView  {...this.webviewProps}/>
    )

}
}


const styles = StyleSheet.create({
    main_container: {
        backgroundColor: 'black'
    },
    webview_container: {
        flex: 1
    }
});

export default LoginImgur

Итак, я нахожусь вмой домашний экран, и я хочу получить этот accessToken обратно, чтобы я мог теперь делать свои вызовы API !!

// Index.js

class Index  extends React.Component {
accessToken : string;

async retrieveItem(key) {
    try {
        const retrievedItem =  await AsyncStorage.getItem(key);
        const item = JSON.parse(retrievedItem);
        return item;
    } catch (error) {
        console.log(error.message);
    }
}

constructor(props) {
    super(props);
}

componentDidMount() {
    this.retrieveItem('ACCESS_TOKEN').then((value) => {
        console.log(value);
        this.accessToken = value;
    }).catch((error) => {
        console.log('Promise is rejected with error: ' + error);
    });
}

_displayAccessToken() {
    console.log(this.accessToken);
}

render() {
    return (
        <View>
            {this._displayAccessToken()}
            <Text>Lol</Text>
        </View>
    )
}

}

Но ..Это не работает вообще.Я действительно получаю токен в console.log, но он не сохраняется в моем this.accessToken.

У кого-нибудь есть идея вытащить его?Было бы очень полезно ... введите описание изображения здесь

1 Ответ

0 голосов
/ 17 ноября 2018

await AsyncStorage.getItem(key); является асинхронным: требуется некоторое время, прежде чем результат станет доступен. render() запускается практически сразу, поэтому в это время this.accessToken еще не установлено.

Один из вариантов отображения маркера доступа - сохранить его состояние компонента. Когда вы вызываете this.setState({ accessToken: value }), render () вызывается снова, поэтому значение будет отображено, как только будет доступен результат.

componentDidMount() {
    this.retrieveItem('ACCESS_TOKEN').then((value) => {
        console.log(value);
        this.setState({accessToken: value }); // cause re-rendering
    }).catch((error) => {
        console.log('Promise is rejected with error: ' + error);
    });
}

render() {
    return (
        <View>
            <Text>{this.state.accessToken}</Text>
            <Text>Lol</Text>
        </View>
    )
}
...