React Native AsyncStorage fetches data after rendering

Based on react-native doc, you can do something like this:

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

You can't make a component wait to render, as far as I know. What I've done in the app I'm working on is to add a loading screen until that promise from AsyncStorage resolves. See the examples below:

//
// With class component syntax
//

import React from 'react';
import {
  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/>;
  }

}
//
// With function component syntax and hooks (preferred)
//

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

const Screen () => {

  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    AsyncStorage.getItem('accessToken').then((token) => {
      setIsLoading(false);
    });
  }, [])

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

}

Setting the isLoading property in state will cause a re-render and then you can show the content that relies on the accessToken.

On a side note, I've written a little library called react-native-simple-store that simplifies managing data in AsyncStorage. Hope you find it useful.

Tags:

React Native