Search code examples
javascriptreactjsreact-nativelocal-storageasyncstorage

Show component only once in React or React Native using localstorage


I am have the following situation where I am trying to show a screen component just once and only once using localstorge. This one is driving me mental.

App.js

...

constructor(props) {
    super(props);
    this.state = {
      isLoading: false,
    };
  }

  componentDidMount() {
    if (AsyncStorage.getItem('key')) {
      AsyncStorage.getItem('key', (value) => {
        this.setState({isLoading: value})
        Alert.alert(JSON.stringify(value))
      });
      AsyncStorage.setItem('key', JSON.stringify(true))
    }
  }

  render() {
    if (!this.state.isLoading) {
      return <Search />
    }
    return <Root />
    }

... 

Solution

  • You need to slightly modify componentDidMount implementation and add another flag to component's state

    constructor() {
       ...
       this.state = {
          isLoaded: false,
          wasShown: false
       }
    }
    
    componentDidMount() {
       AsyncStorage.getItem('key') // get key
         .then(wasShown => {
             if(wasShown === null) { // first time 
               // we need to save key for the next time
               AsyncStorage.setItem('key', '"true"')
             }
    
             this.setState({isLoaded: true, wasShown})
          })
      }
    
    render() {
      const { isLoaded, wasShown } = this.state
    
      // you can't tell if this component was shown or not render nothing
      if(!isLoaded) { return null }
    
      if(!wasShown) {
        return <Search />
      } 
    
      return <Root/>
    }
    

    BTW if you include async/await support to your babel presets you could make this code way simpler

    async componentDidMount() {
       const wasShown = await AsyncStorage.getItem('key') // get key
    
       if(wasShown === null) {
         await AsyncStorage.setItem('key', '"true"')
       }
    
       this.setState({isLoaded: true, wasShown}
      }