skip to Main Content

The output error like this:

TypeError: TypeError: undefined is not an object (evaluating ‘_this.state.userInfo.picture.data’)

there I just want passing data from facebook into my view in react native . it says undefined is not an object, how to fix this ?

Here is the HomeScreen component’s code:

import React, { Component } from 'react';
import { Text, TouchableOpacity, ScrollView, View, StyleSheet, Button, Alert, Image } from 'react-native';
import Expo, { Constants } from 'expo';

export default class HomeScreen extends Component {

    constructor(props){
        super(props);
        this.state = { userInfo: null }
    }

    async logInFB() {
        try {
          const {
            type,
            token,
            expires,
            permissions,
            declinedPermissions,
          } = await Expo.Facebook.logInWithReadPermissionsAsync('214751749451960', {
            permissions: ['public_profile'],
          });
          if (type === 'success') {
            // Get the user's name using Facebook's Graph API
            const response = await fetch(`https://graph.facebook.com/me?access_token=${token}&fields=id.name.picture.type(large)`);
            const userInfo = await response.json();
            this.setState({ userInfo });
            Alert.alert('Logged in!', `Hi ${(await response.json()).name}!`);
          } else {
            // type === 'cancel'
          }
        } catch ({ message }) {
          alert(`Facebook Login Error: ${message}`);
        }
    }

    _renderUserInfo = () => {
        return(
            <View style={{ alignItems:'center' }}>
                <Image
                    source={{ uri: this.state.userInfo.picture.data.url}}
                    style={{width:100, height:100, borderRadius:50}}
                />
                <Text style={{ fontSize:20 }}>
                    { this.state.userInfo.name }
                </Text>
                <Text>ID: { this.state.userInfo.id }</Text>
            </View>
        );
    }


    render(){
        return(
            <View style={styles.container}>
                <Text>welcome to my apps!</Text>
                { !this.state.userInfo ? (<Button title="Connect with facebook" onPress={this.logInFB.bind(this)}/>) : (this._renderUserInfo())}
            </View>
        );
    }
}

Here is the styling (They are both on the same file):


const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#34495e',
  },
});

Thanks in advance 🙂

4

Answers


  1. Try declare your userInfo in your state this way.

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

    It’s possible that your “this.state.userInfo” in this line

    source={{ uri: this.state.userInfo.picture.data.url}}
    

    is still null, hence, null.picture.data.url where null is not an object.

    Login or Signup to reply.
  2. Instead of

    import Expo, { Constants } from 'expo';
    

    Try

    import { Facebook, Constants } from 'expo';
    

    Then change

    await Expo.Facebook.logInWithReadPermissionsAsync
    

    to

    await Facebook.logInWithReadPermissionsAsync
    

    see https://forums.expo.io/t/import-expo-from-expo-has-been-deprecated/15799

    Login or Signup to reply.
  3. From the code it’s very clear that this.state.userInfo.picture.data.url chain traversing has undefined somewhere in between.

    I’m not giving the exact solution but a suggestion to avoid this type of errors known as null pointer exceptions .

    Please use some simple util library like idx for traversing properties on objects.

    // Using regular JavaScript 
    
    getSourceURL = () => {
      if( this 
        && this.state 
        && this.state.userInfo 
        && this.state.userInfo.picture 
        && this.state.userInfo.picture.data 
        && this.state.userInfo.picture.data.url) {
        return this.state.userInfo.picture.data.url;
      } 
    }
    

    You can achieve the same using idx as below

    // Using idx 
    
    getSourceURL = () => {
      if( idx(this, _ => _.state.userInfo.picture.data.url )) {
        return this.state.userInfo.picture.data.url;
      }
    }
    
    Login or Signup to reply.
  4. Try not to set state to null anyway! You can initialize like this :

     userInfo : {
        picture: { }
     }
    

    According to component lifecycles constructor will execute first. Your task is asynchronous so the state will stay null till data is retrieved from server.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search