1

I'm writing a React Native app and I'm having trouble understanding how to complete a functionality. Basically when the user logs in, I'm using AsyncStorage to save the value of an access token to a variable, but then I need to access that variable to send to the API as part of the header.

I'm using getItem to access the storage but it's returning a promise, which I can't really pass as part of the header as it's expecting a String. When I console.log the return, it does show as a string in the console, though.

So the main problem is the API expecting a string that contains the access_token that's buried in the Promise, and passing the Promise to the API is not working as I'm getting an Bad Request error.

Here's the code for the Edit User page, the getToken() and userUpdate() functions is where the problem lies.

'use strict'

import React, {Component} from 'react';
import {AsyncStorage, Text, View, TouchableHighlight} from 'react-native';
import {Actions, ActionConst} from 'react-native-router-flux';
import t from 'tcomb-form-native';
import _ from 'lodash';
import EStyleSheet from 'react-native-extended-stylesheet';

import GlobalStyles from '../styles/GlobalStyles';

import Global from '../components/Global';
import ViewContainer from '../components/ViewContainer';
import StatusBarBackground from '../components/StatusBarBackground';

let Form = t.form.Form;

var User = t.struct({
    email: t.String,
    firstName: t.String,
    lastName: t.String,
});

const options = {
    fields: {
        email: {
            autoCapitalize: 'none',
            autoCorrect: false,
            editable: false,
        },
        mobilePhone: {
            editable: false,
        }
    }
};

EStyleSheet.build(GlobalStyles);

class EditProfileScreen extends Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedTab: "EditProfileScreen",
            value: {
                email: Global.email,
                firstName: Global.firstName,
                lastName: Global.lastName
            }
        };
    }

    async _getToken(key) {
        AsyncStorage.getItem(key, (err, result) => {
            return result
        })
    }

    _userUpdate() {
        var value = this.refs.form.getValue();
        var access_token = this._getToken(Global.ACCESS_TOKEN)
        console.log(access_token)
        if (value) {
            fetch("https://test-integration.herokuapp.com/accounts/mine", {
                method: "PUT",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${access_token}`
                },
                body: JSON.stringify({firstName: value.firstName, lastName: value.lastName})
            }).then((response) => response.json()).then((responseData) => {
                if (responseData) {
                    console.log(responseData)
                } else {
                    AlertIOS.alert("Login failed due to: " + responseData.message)
                }
            })
            .done()
        }
    }

    render() {
        return (
            <ViewContainer style={styles.viewContainer}>
                <Text style={styles.title}>
                    Edit Profile
                </Text>
                <View>
                    <Form ref="form" type={User} options={options} value={this.state.value} />
                </View>
                <View style={styles.row}>
                    <TouchableHighlight style={styles.button} onPress={this._userUpdate.bind(this)} underlayColor='#99d9f4'>
                        <Text style={styles.buttonText}>{_.capitalize('Confirm Edit')}</Text>
                    </TouchableHighlight>
                </View>
            </ViewContainer>
        );
    }
};

var styles = EStyleSheet.create({
    viewContainer: {
        justifyContent: 'center',
        padding: 20,
        backgroundColor: '$white',
    },

    title: {
        fontFamily: '$ralewayThin',
        color: '$primaryText',
        fontSize: 30,
        alignSelf: 'center',
        marginBottom: 30
    },

    buttonText: {
      fontFamily: '$ralewayRegular',
      fontSize: 18,
      color: '$white',
      alignSelf: 'center'
    },
    button: {
      height: 36,
      backgroundColor: '$primaryTeal',
      borderRadius: '$borderRadius',
      marginBottom: 10,
      marginLeft: 30,
      marginRight: 30,
      alignSelf: 'stretch',
      justifyContent: 'center'
    },

    row: {
        marginTop: 20
    }
});

module.exports = EditProfileScreen;

Any ideas would be greatly appreciated!

Kaidao
  • 115
  • 3
  • 16
  • 5
    [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323) – Thomas Aug 19 '16 at 17:05
  • Hey Thomas, Thanks for the comment. Unfortunately I'm still not too sure how to pass the Promise for the API to accept. I'm still getting the Bad Request response because it's passing a Promise instead of the string. – Kaidao Aug 19 '16 at 18:50

1 Answers1

2

You don’t have to define _getToken as an async function if you don’t return the promise via await. Anyway, first you’ll have to return the promise the one or the other way:

// async style
async _getToken(key) {
    return await AsyncStorage.getItem(key, (err, result) => {
        return result;
    });
}
// or old style
_getToken(key) {
    return AsyncStorage.getItem(key, (err, result) => {
        return result;
    });
}

But when it gets to _userUpdate, async functions really come in handy. You declare it as async and await the value of the token being returned before the rest of the function is executed.

async _userUpdate() {
    var value = this.refs.form.getValue();
    var access_token = await this._getToken(Global.ACCESS_TOKEN)
    console.log(access_token)
    ...
}

This should do the trick.

If you want to get a better understanding of how the async/await works, check out this article.

Oliver
  • 507
  • 6
  • 12
  • Thanks Oliver! This solved my problem. I needed to await for the value back to pass it to the API. – Kaidao Aug 19 '16 at 20:52