简体   繁体   中英

Use AsyncStorage to store token globally

I'm learning react-native since one week and i'm confused about something.

Here is the stuff: I'm developing an app parsing Imgur API, I somehow managed via a Webview to authenticate myself and get an accessToken, refreshToken etc which I stored locally on my webview component.

Now I want to store this token globally on the app so I did some research and found about AsyncStorage (visibly not secure to store tokens but it's fine it's just an app to practice).

So here is what I understood:

  • You give a key and a value via setItem, they wrap it somehow in a Promise (I need to do some research about this stuff)
  • Then you can get it back in another async function.

So here is what I did to set my item in my Login component:

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

So now I'm in my homescreen and I want to get this accessToken back so I can now make my API calls !!

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

}

But... It's not working at all. I do get the token in the console.log actually but it doesn't get save in my this.accessToken.

Someone have an idea to pull it of ? Would be a great help... enter image description here

await AsyncStorage.getItem(key); is async: it takes a while before the result is available. render() runs almost immediately, so at that time this.accessToken is not set yet.

One option to display the accesstoken is to store it the component's state. When you call this.setState({ accessToken: value }) , render() is called again, so then the value will be rendered as soon as the result is available.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM