R. R.
R. R.

Reputation: 31

React Native - async/await does not work

Is it possible to use async/await outside of classes? For example I use AsyncStorage to store access token and want to get this token before StackNavigator will be initialized.

container.js

import React from 'react';
import { StackNavigator } from 'react-navigation';
import PairingView from '../components/PairingView';
import MainView from '../components/MainView';
import { getTokenFromStorageAsync } from '../helpers/asyncStorageHelper';

const accessToken = getTokenFromStorageAsync().done();
console.log(accessToken);   <---------- undefined

const AppNavigator = StackNavigator({
  PairingRoute: {
    screen: PairingView
  },
  MainRoute: {
    screen: MainView
  }
}, {
  initialRouteName: (accessToken == null) ? 'PairingRoute' : 'MainRoute',
  initialRouteParams: {
    token: accessToken
  }
});

const App = () => (
  <AppNavigator />
);

export default App;

asyncStorageHelper.js

import { AsyncStorage } from 'react-native';

export const getTokenFromStorageAsync = async () => {
  try {
    const value = await AsyncStorage.getItem('@nfs:token');
    console.log(value);   <---------- access token
    if (value != null)
      return value;
  } catch (err) {
    console.error(err);
  }
  return undefined;
};

Upvotes: 1

Views: 10473

Answers (2)

R. R.
R. R.

Reputation: 31

Solved the problem.

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      accessToken: 'fetching'
    };

    this._loadAccessToken();
  }

  _loadAccessToken = async () => {
    const token = await getTokenFromStorageAsync();
    this.setState({ accessToken: token });
  }

  render() {
    if (this.state.accessToken === 'fetching')
      return null;

    const AppNavigator = StackNavigator({
      PairingRoute: {
        screen: PairingView
      },
      MainRoute: {
        screen: MainView
      }
    }, {
      initialRouteName: (this.state.accessToken == null) ? 'PairingRoute' : 'MainRoute',
      initialRouteParams: {
        token: this.state.accessToken
      }
    });

    return <AppNavigator />;
  }
}

export default App;

Upvotes: 2

Forivin
Forivin

Reputation: 15548

getTokenFromStorageAsync().then(accessToken => {
    console.log(accessToken);
    // ...
});

or

// ...
export default (async () => {

    const accessToken = await getTokenFromStorageAsync();
    console.log(accessToken);

    const AppNavigator = StackNavigator({
      PairingRoute: {
        screen: PairingView
      },
      MainRoute: {
        screen: MainView
      }
    }, {
      initialRouteName: (accessToken == null) ? 'PairingRoute' : 'MainRoute',
      initialRouteParams: {
        token: accessToken
      }
    });

    const App = () => (
      <AppNavigator />
    );

    return App;

})()

As you can see you have to export a promise that resolves with your App, instead of exporting your App directly.

Edit:

import { AppRegistry } from 'react-native';
import App from './app/container';
(async () => {
    let ResolvedApp = await App()
    AppRegistry.registerComponent('someappname', () => ResolvedApp);
    // ...
})()

Upvotes: 0

Related Questions