1

Trying to use a AsyncStorage variable to conditionally render content.

My app uses createBottomTabNavigator from react-navigation. I have a tab called Settings that must conditionally render content based on wether a user is logged in or not (checking AsyncStorage). The following code works on first render but another tab can update AsyncStorage value, returning back to Settings tab it still renders initial content.

Which approach can i use to achieve this, i'm also trying to use shouldComponentUpdate but i'm not sure how it works.

import React, {Component} from 'react'; 

class Settings extends React.Component{

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

//I want to use this method but not sure how.
shouldComponentUpdate(nextProps, nextState){
 // return this.state.isLoggedIn != nextState; 
}

componentDidMount(){
  console.log("componentWillUpdate..");
  this.getLocalStorage();
}

getLocalStorage = async () => {
  try { 
    const value = await AsyncStorage.getItem('username');  
    if(value !== null) {
      this.setState({isLoggedIn:true});
    } 
  } catch(e) {
    // error reading value
  }
}

render() {   
    if(this.state.isLoggedIn)
    {
      return( 
          <View>
              <Text style={styles.title_header}>Logged In</Text>
          </View>  
      );
    }
    else{
      return( 
          <View>
              <Text style={styles.title_header}>Logged Out</Text>
          </View> 
      );
    }  
 }
}

export default Settings;

})
Africa Matjie
  • 351
  • 2
  • 17

2 Answers2

2

The problem comes from react-navigation createBottomTabNavigator. On first visit, the component is mounted and so componentDidMount is called and everything is great.

However, when you switch tab, the component is not unmounted, which means that when you come back to the tab there won't be any new call to componentDidMount.

What you should do is add a listener to the willFocus event to know when the user switches back to the tab.

componentDidMount() {
  this.listener = this.props.navigation.addListener('willFocus', () => {
    AsyncStorage.getItem('username').then((value) => {
      if (value !== null) {
        this.setState({ isLoggedIn: true });
      }
      catch(e) {
        // error reading value
      }
    });
  });
}

Don't forget to remove the listener when the component is unmounted:

componentWillUnmount() {
  this.listener.remove();
}
remeus
  • 2,066
  • 2
  • 9
  • 17
2

Use NavigationEvents. Add event listeners to your Settings components.

onWillFocus - event listener

onDidFocus - event listener

onWillBlur - event listener

onDidBlur - event listener

for example, the following will get fired when the next screen is focused.

focusSubscription = null;

onWillFocus = payload => {
    // get values from storage here
};

componentDidMount = () => {
  this.focusSubscription = this.props.navigation.addListener(
    'willFocus',
    this.onWillFocus
  );
};

componentWillUnmount = () => {
  this.focusSubscription && this.focusSubscription.remove();
  this.focusSubscription = null;
};
Community
  • 1
  • 1
Junius L.
  • 14,324
  • 4
  • 33
  • 63