TypeError: null is not an object (evaluating 'son['businesses']')

2.3k views Asked by At

Im getting this error "TypeError: null is not an object (evaluating 'son['businesses']')" Im not sure what is the issue is because when I was writing 'son['businesses'][1]['name']', I started with just 'son' and when i added '['businesses'][1]['name']' no error was thrown. but as I restarted my simulator it now throws an error.

const [son, setSon] = useState(null);
fetch("https://api.yelp.com/v3/businesses/search?term=burger&location=90706&limit=2", requestOptions)
            .then(response => response.json())
            .then(result => db.collection("group")
            .doc(roomCode)
            .set(result))
            .catch(error => console.log('error', error));
const fetchData = async () => {
        try {
            await db
                .collection('group')
                .doc(route.params.roomCode)
                .get()
                .then((documentSnapshot) => {
                    if (documentSnapshot.exists) {
                        setSon(documentSnapshot.data());
                    } else {
                        console.log('hello');
                    }
                })

        } catch (err) {
            Alert.alert('There is something wrong!', err.message);
        }
    }
 useEffect(() => {
        console.log('completed');
        fetchData();
        
        console.log('son', son['businesses'][1]['name']);
        
    }, []);
import React, {useRef} from "react";
import { useEffect, useState } from 'react';
import { useNavigation } from '@react-navigation/core';
//import { NavigationContainer } from '@react-navigation/native';
//import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { StyleSheet, Text, TouchableOpacity, Alert, View, Image, FlatList, SafeAreaView} from "react-native";
import styles from "./styles";
import { doc, setDoc, getDoc, onSnapshot } from "firebase/firestore"; 
import { db, auth } from "../../firestore";
import firebase from "firebase";
import Icon from 'react-native-vector-icons/FontAwesome';
import IconMaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import Swiper from "react-native-deck-swiper";
import {BEARER_TOKEN} from '../hooks/yelp-api/config';

const DUMMY_DATA = [
    {
        restaurantName: 'Marufuku Ramen',
        occupation: "bricks",
        photoURL: "https://s3-media0.fl.yelpcdn.com/bphoto/ouK2VmW0SrI70jsJpTxJhw/1000s.jpg",
        age: 27,
        id: 123,

    },
    {
        restaurantName: 'Farmhouse Kitchen Thai Cuisine',
        occupation: "nothing",
        photoURL: "https://s3-media0.fl.yelpcdn.com/bphoto/kUlEaPpv0JGlHG_nrPr7wQ/1000s.jpg",
        age: 23,
        id: 124,
    },
    {
        restaurantName: 'Sotto Mare Oysteria & Seafood',
        occupation: "everything",
        photoURL: "https://s3-media0.fl.yelpcdn.com/bphoto/o3hIcGLMxV_5ynxEjGWGrw/1000s.jpg",
        age: 99,
        id: 125,
    }
]


const GroupSwipe = ({navigation, route, roomZipCode}) => {
    const roomCode = route.params.roomCode;
    const swipeRef = useRef(null);
    const [son, setSon] = useState({});
    //const [result, setresult] = useState()
    console.log('roomZipCode',roomZipCode);
    useEffect(() =>{
        var myHeaders = new Headers();
        myHeaders.append("Authorization", BEARER_TOKEN);
    
        var requestOptions = {
            method: 'GET',
            headers: myHeaders,
            redirect: 'follow'
        };
    
        fetch("https://api.yelp.com/v3/businesses/search?term=burger&location=90706&limit=2", requestOptions)
            .then(response => response.json())
            .then(result => db.collection("group")
            .doc(roomCode)
            .set(result))
            .catch(error => console.log('error', error));
            

    })

        
    const fetchData = async () => {
        try {
            await db
                .collection('group')
                .doc(route.params.roomCode)
                .get()
                .then((documentSnapshot) => {
                    if (documentSnapshot.exists) {
                        setSon(documentSnapshot.data());
                    } else {
                        console.log('hello');
                    }
                })

        } catch (err) {
            Alert.alert('There is something wrong!', err.message);
        }
    }
    
        
    useEffect(() => {
        console.log("completed");
        fetchData().then((data) => {
            setSon(data);
            console.log("son", son["businesses"][1]["name"]);
        })
    }, []);
    // useEffect(() => {
    //     console.log('completed');
    //     fetchData();
        
    //     console.log('son', son['businesses'][1]['name']);
        
    // }, []);
    return (
        <SafeAreaView style={styles.safe}>
            <View style={styles.buttonContainerHome}>
                <TouchableOpacity
                    onPress={() => navigation.navigate('GroupStart') }
                    style={styles.buttonHome}
                >
                    <Text style={styles.buttonTextHome}>FOOD FIGHT</Text>
                </TouchableOpacity>
            </View>
            <View style={styles.roomId}>    
                <Text style ={styles.roomIdText}>Room ID: {roomCode}</Text>
            </View>
            {/* <View style={styles.resturantName}>
                <Text style ={styles.resturantNameText}>Chick Fil A</Text>
            </View>  */}
            <View style={styles.cards}>
                <Swiper 
                ref={swipeRef}
                    containerStyle={{backgroundColor: 'transparent'}}
                    cards={DUMMY_DATA}
                    stackSize={3}
                    cardIndex={0}
                    animateCardOpacity
                    verticalSwipe={false}
                    renderCard={(card) => (
                        <View style={styles.cardstyle}
                        key={card.id} >
                            {/* style={tw("relative bg-white h-3/4 rounded-xl")}> */}
                            <Text style={{alignSelf: 'center', margin:10, fontSize: 18, fontWeight: 'bold',}}>{card.restaurantName}</Text>
                            <Image 
                                style={{ alignSelf: 'center', width: 300,
                                height: 300,resizeMode: 'contain', borderRadius: 5, 
                                margin:15, borderRadius: 20, justifyContent: 'center'}}
                                source={{ uri: card.photoURL }}
                                />
                        </View>
                        
                    )}
                />
            </View>
            <View style = {styles.functionList}>           
                    <TouchableOpacity onPress={() => {}} style = {styles.functionButton}>                   
                        <Icon name="undo" size={50} color="#ECD55D" />
                    </TouchableOpacity>
                    <TouchableOpacity onPress={() => swipeRef.current.swipeLeft()} style = {styles.functionButton}>
                        <Icon name="times-circle-o" size={80} color="#AA4747" />
                    </TouchableOpacity>
                    <TouchableOpacity onPress={() => swipeRef.current.swipeRight()} style = {styles.functionButton}>
                        <Icon name="check-circle-o" size={80} color="#9DC151" />
                    </TouchableOpacity>
                    <TouchableOpacity onPress={() => {}} style = {styles.functionButton}>
                        <IconMaterialCommunityIcons name="star-circle-outline" size={55} color="#75B9DF" />
                    </TouchableOpacity>
                
            </View>
        </SafeAreaView>
        
    )
}

export default GroupSwipe


[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'son["businesses"][1]')] at node_modules/@firebase/storage/dist/index.browser.esm.js:3561:30 in UploadTaskCompat.prototype.on

I have tried to use async function and await for the fetchData() but it didnt solve the issue.

1

There are 1 answers

7
J Singh On

useEffect runs when the component mount, update (if there are dependencies), and unmount (if there is a return method).

What's happening here is when the component mount, it fires off useEffect and the following things happen:

  • console.log('completed') runs right away
  • then the second line executes fetchData() which is an async call and because you're not awaiting it here, the third line executes console.log('son', son['businesses'][1]['name']); and at that point, the fetchData is still trying to fetch the data from the API and therefore the third line fails as the son is still null.

The easiest solution to this is to do something like this:

useEffect(() => {
  console.log("completed");
  fetchData().then((data) => {
      setSon(data);
      console.log("son", son["businesses"][1]["name"]);
  })
}, []);