user photo in tab navigation

In a react native project I am trying to set the user's profile photo as a tabBarIcon in tabNavigation. Below is how I am trying to retrieve the photo path and set it in the source for TabBarIcon.

First I have a token in AsyncStorage that gives me the username, email, or phonenumber of the user after login (works fine). This is in my constructor:

constructor(props) {
  super(props)

  this.state = {
    Access: []
  }

}

I set the Access in my state to a value in my AsyncStorage with getItem('Access') which i know works fine.

Now i have a function getProfilePhoto where I use fetch to get the profile photo.

getProfilePhoto = () => {

  const { Access } = this.state.access;

  fetch('http://urltofiletogetprofilephoto', {
    method: 'POST',
    headers: {
      'Accept':'application/json',
      'Content-Type':'application/json',
    },
    body: JSON.stringify({
      Access:Access
    })
  }).then((response) => response.json())
    .then((responseJson) => {
      if(responseJson === 'NULL') {
        console.log('../Images/NoPhoto.png');
      } else {
        console.log('../' + responseJson);
      }
    })

}

What I return from that file is:

$profilephoto = $row['ProfilePhoto'];
$profilephotoJson = json_encode($profilephoto);
echo $profilephotoJson;

That should return something like "Images/userprofilephoto.png". Now in navigationOptions I have this:

static navigationOptions = {
    tabBarLabel: 'Profile',
    tabBarIcon: ({ tintColor }) => (
        <Image
            source = {this.getProfilePhoto}
            style={[styles.icon, {tintColor: tintColor}]}
        />
    )
}

I thought calling the function would print the returned Image path, but when I run the app on my device I don't get an error but my tabBarIcon Image is just blank. I am new to react native and haven't worked with Json much I am hoping someone will be able to see something wrong that I am missing!

2 answers

  • answered 2017-11-14 23:25 aqwert

    try

    source={require(this.getProfilePhoto())}
    

    However your function getProfilePhoto is not returning a path as you are using fetch.

    Also navigationOptions is static, so this is not available.

    You will need to access it via navigation params

    static navigationOptions = ({ navigation }) => {
    const { state } = navigation;
        return {
            tabBarLabel: 'Profile',
            tabBarIcon: ({ tintColor }) => (
                <Image
                    source = {state.params.getImage()}
                    style={[styles.icon, {tintColor: tintColor}]}
                />
            )
        }
    }
    
    componentWillMount() {
        this.props.navigation.setParams({
          getImage: () => {
            this.getProfilePhoto();
          },
        });
      }
    
    getProfilePhoto () => {
        //here you can get the path from this.props which would be added
        //as before the component mounts
        return this.props.profileImagePath;  //set from redux connect
    }
    

    One downside with this is that if you want to update the image on the fly, you will need to call setParams again to force it to re-render the tab.

     componentWillReceiveProps(nextProps) {
       this.props.navigation.setParams({
          getImage: () => {
            this.getProfilePhoto();
          },
        });
     }
    

    I would have the action of getting the image separate to the component, and use Redux to connect to the latest image path. You can therefore set the Redux store triggered from another component.

  • answered 2017-11-14 23:35 Nandu Kalidindi

    You probably need to setState when your promise resolved by adding the data fetching request in the comoponentWillMount hook and make sure your image resides in the generated location relative to your component.

    class UserProfile extends React.Component {
      constructor(props) {
        super(props)
    
        this.state = {
          Access: []
          image: null
        }
    
      }
    
      componentWillMount() {
        this.getProfilePhoto();
      }
    
      getProfilePhoto = () => {
    
        const { Access } = this.state.access;
    
        fetch('http://urltofiletogetprofilephoto', {
          method: 'POST',
          headers: {
            'Accept':'application/json',
            'Content-Type':'application/json',
          },
          body: JSON.stringify({
            Access:Access
          })
        }).then((response) => response.json())
          .then((responseJson) => {
            if(responseJson === 'NULL') { 
              console.log("../Images/NoPhoto.png");
            } else {
              this.setState({image: responseJson})
            }
          })
    
      }
    
      render() {
        return (
           this.state.image
             ?
             <Image
               source={require(this.state.image)}
               style={this.props.style}
             />
             : 
             null
        )        
      } 
    }
    
    
    static navigationOptions = {
        tabBarLabel: 'Profile',
        tabBarIcon: ({ tintColor }) => (
            <UserProfile
                style={[styles.icon, {tintColor: tintColor}]}
            />
        )
    }