Home > Enterprise >  Getting TypeError: null is not an object in my react native app
Getting TypeError: null is not an object in my react native app

Time:03-21

After logging in, the user is redirected to profile page, where I fetch data from firestore (firebase) and then use it to display the profile details, but I am getting render error TypeError: null is not an object. I checked that my firestore document has all data which I am fetching..

My Profile Page Source Code ->

import { StyleSheet, View, Text, ScrollView, Image, TouchableOpacity } from "react-native";
import auth from '@react-native-firebase/auth';
import firestore from '@react-native-firebase/firestore'

function App() {
    const [userData, setUserData] = useState(null);
    const user = auth().currentUser;
    const data = firestore().collection('users').doc(user.uid).get().then(documentSnapshot => {
        setUserData(documentSnapshot.data())
    })

    return (
        <View style={styles.container}>
            <ScrollView style={styles.scrollView} contentContainerStyle={styles.contentContainer}>
                <View style={{alignSelf: 'center', margin: 20}}>
                    <View style={styles.userImg}>
                        <Image source={{uri: 'https://i.imgur.com/Wceq3H2.png'}} style={styles.image} resizeMode='center' />
                    </View>
                </View>
                <View style={styles.userData}>
                    <Text style={styles.userName}>Name: {userData.name}</Text>
                    <Text style={styles.userName}>Age: {userData.age}</Text>
                    <Text style={styles.userName}>Gender: {userData.gender}</Text>
                    <Text style={styles.userEmail}>Email: {userData.email}</Text>
                    <Text style={styles.userName}>Phone Number: {userData.phone}</Text>
                    <Text style={styles.userName}>Blood Group: {userData.blood}</Text>
                    <Text style={styles.userName}>Height: {userData.height}</Text>
                    <Text style={styles.userName}>Weight: {userData.weight}</Text>
                <View style={styles.text}>
                    <Text style={styles.subtext}>Want to Sign Out?</Text>
                    <TouchableOpacity onPress={() => auth().signOut()} style={{marginHorizontal: 5}}>
                        <Text style={{color: 'rgba(81,135,200,1)'}}>Sign out here</Text>
                    </TouchableOpacity>
                </View>
                </View>
            </ScrollView>
        </View>
    )
}

export default App;

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#393636'
    },
    scrollView: {
        height: '20%',
        width: '100%',
        padding: 0,
        borderWidth: 0,
        borderRadius: 0,
    },
    contentContainer: {
        paddingBottom: 50
    },
    userImg: {
        width: 200,
        height: 200,
        borderRadius: 100,
        overflow: "hidden",
        paddingTop: 50
    },
    image: {
        flex: 1,
        height: undefined,
        width: undefined
    },
    userData: {
        marginLeft: 20,
        marginRight: 20,
        marginBottom: 20,
        padding: 30,
        borderRadius: 30,
        flex: 1,
        backgroundColor: '#302C2C',
        marginTop: 60
    },
    userName: {
        fontSize: 18,
        color: '#daf1f1',
        margin: 5
    },
    userEmail: {
        fontSize: 18,
        color: '#daf1f1',
        margin: 5
    },
    text: {
        flexDirection: "row",
        marginBottom: 20,
        marginTop: 8
    },
    subtext: {
        marginHorizontal: 5,
        color: '#a6a6a6'
    }
})```

CodePudding user response:

I suggest you use the hook useEffect from React when the screen did mount to fetch the data and add it to a state to display on the screen. Another tip, use the optional chaining operator to avoid the error when a property does not exist on an object and it is accessed. In your case, the userData is initialized as null. The code will be like this:

import React, { useState, useEffect } from 'react'
import { StyleSheet, View, Text, ScrollView, Image, TouchableOpacity } from "react-native";
import auth from '@react-native-firebase/auth';
import firestore from '@react-native-firebase/firestore';

function App() {
  const [userData, setUserData] = useState(null);
  const user = auth().currentUser;

  const fetchDataFromFirestore = () => {
    firestore().collection('users').doc(user.uid).get().then(documentSnapshot => {
      setUserData(documentSnapshot.data())
    })
  }

  useEffect(() => {
    fetchDataFromFirestore()
  }, [])

  return (
    <View style={styles.container}>
      <ScrollView style={styles.scrollView} contentContainerStyle={styles.contentContainer}>
        <View style={{alignSelf: 'center', margin: 20}}>
          <View style={styles.userImg}>
            <Image source={{uri: 'https://i.imgur.com/Wceq3H2.png'}} style={styles.image} resizeMode='center' />
          </View>
        </View>
        <View style={styles.userData}>
          <Text style={styles.userName}>Name: {userData?.name}</Text>
          <Text style={styles.userName}>Age: {userData?.age}</Text>
          <Text style={styles.userName}>Gender: {userData?.gender}</Text>
          <Text style={styles.userEmail}>Email: {userData?.email}</Text>
          <Text style={styles.userName}>Phone Number: {userData?.phone}</Text>
          <Text style={styles.userName}>Blood Group: {userData?.blood}</Text>
          <Text style={styles.userName}>Height: {userData?.height}</Text>
          <Text style={styles.userName}>Weight: {userData?.weight}</Text>
          <View style={styles.text}>
            <Text style={styles.subtext}>Want to Sign Out?</Text>
            <TouchableOpacity onPress={() => auth().signOut()} style={{marginHorizontal: 5}}>
              <Text style={{color: 'rgba(81,135,200,1)'}}>Sign out here</Text>
            </TouchableOpacity>
          </View>
        </View>
      </ScrollView>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#393636'
  },
  scrollView: {
    height: '20%',
    width: '100%',
    padding: 0,
    borderWidth: 0,
    borderRadius: 0,
  },
  contentContainer: {
    paddingBottom: 50
  },
  userImg: {
    width: 200,
    height: 200,
    borderRadius: 100,
    overflow: "hidden",
    paddingTop: 50
  },
  image: {
    flex: 1,
    height: undefined,
    width: undefined
  },
  userData: {
    marginLeft: 20,
    marginRight: 20,
    marginBottom: 20,
    padding: 30,
    borderRadius: 30,
    flex: 1,
    backgroundColor: '#302C2C',
    marginTop: 60
  },
  userName: {
    fontSize: 18,
    color: '#daf1f1',
    margin: 5
  },
  userEmail: {
    fontSize: 18,
    color: '#daf1f1',
    margin: 5
  },
  text: {
    flexDirection: "row",
    marginBottom: 20,
    marginTop: 8
  },
  subtext: {
    marginHorizontal: 5,
    color: '#a6a6a6'
  }
})

export default App;

CodePudding user response:

Try this

const unmounted = useRef(false);
const getData = () => {
    if (!unmounted.current) {
      const data = firestore().collection('users').doc(user.uid).get().then(documentSnapshot => {
          setUserData(documentSnapshot.data())
          setUserData(data)
        }
      }
      useEffect(() => {
        getData()
        return () => {
          unmounted.current = true;
        };
      }, [])

the problem is that you are not using useEffect..

  • Related