skip to Main Content

.Can anyone can tell me How can i fix this error ERROR TypeError: undefined is not an object (evaluating ‘userData.username’)

I am building a small app so when you login in app and enter main page than you need to allow permission to get your city name location after frontend gets your city name then it will send your city name to the backend to save your city name in the database and your city name will be saved in database "city is a string" till here everything works fine and its saving my city name into MongoDB database

Now i have a screen in my app so i want that when a user enters that screen then that user will get one random user username and profile pic displayed in frontend note both users should have the same city name in the database the user who requested to server should have the same city as other one random user in the database and i will two same users having same city

Mainpage:

import { StyleSheet, View, StatusBar } from 'react-native'
import React, { useEffect, useState } from 'react'
import Bottomnavbar from '../../Components/Bottomnavbar'
import TopNavbar from '../../Components/TopNavbar'
import FollowersRandomPost from '../../Components/FollowersRandomPost'
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Location from 'expo-location';

const Mainpage = ({ navigation }) => {
  
  const [userdata, setUserdata] = useState(null);
  const [location, setLocation] = useState(null);
  const [errorMsg, setErrorMsg] = useState(null);
  const [city, setCity] = useState(null);

  useEffect(() => {
    async function getUserData() {
      try {
        const userDataString = await AsyncStorage.getItem('user');
        const userData = JSON.parse(userDataString);
        setUserdata(userData);
      } catch (err) {
        alert(err);
      }
    }

    getUserData();
  }, []);

  useEffect(() => {
    async function getLocation() {
      try {
        let { status } = await Location.requestForegroundPermissionsAsync();
        if (status !== 'granted') {
          setErrorMsg('Permission to access location was denied');
        }

        let location = await Location.getCurrentPositionAsync({});
        setLocation(location);

        let city = await Location.reverseGeocodeAsync(location.coords);
        setCity(city[0].city);
      } catch (err) {
        console.error(err);
      }
    }

    getLocation();
  }, []);

  useEffect(() => { 
    async function sendCity() {
       try {
        const response = await fetch('http://10.0.2.2:3000/updateCity', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            city: city,
            username: userdata.user.username
          }),
        });
        const data = await response.json();
        console.log('Success:', data);
      } catch (err) 
        console.error('Error:', err);
      }
    }
    if (userdata && city) {
      sendCity();
    }
  }, [userdata, city]);

console.log(city)
  return (
    <View style={styles.container}>
      <StatusBar />
      <TopNavbar navigation={navigation} page={"MainPage"} />
      <Bottomnavbar navigation={navigation} page={"MainPage"} />
      <FollowersRandomPost />
    </View>
  );
}


export default Mainpage

Route which updates the city:

router.post('/updateCity', (req, res) => {

    const city = req.body.city;
    const username = req.body.username;

    console.log(city)

    console.log(`Updating city for user ${username} to ${city}`);

    User.findOneAndUpdate({ username: username }, { city: city }, (err, user) => {
        if (err) {
            return res.status(500).json({
                error: err
            });
        }
        res.status(200).json({
            message: 'City updated successfully'
        });
    });
});

Screen where i want username and profile pic to display:

import { StyleSheet, Text, View, Image } from 'react-native'
import React, { useState, useEffect } from 'react'

const SearchUserPage = () => {
  return (
    <View style={styles.container}>
      <View style={styles.userSection}>
        <View style={styles.imageContainer}>
          <Image
            style={styles.image}
            source={profile pic here}
            resizeMode="contain"
            overflow="hidden"
          />
        </View>
        <Text style={styles.text}>User name here</Text>
      </View>
    </View>
  )
}

export default SearchUserPage

Backend code which gets one random user having same city :

router.get("/user", async (req, res) => {
    try {
      const city = req.body.city;
  
      console.log(city);
  
      const count = await User.countDocuments({ city: city });
      if (count === 0) {
        return res.status(404).json({ error: "No users found with that city" });
      }
  
      const randomUser = await User.aggregate([
        {
          $match: {
            city: city,
          },
        },
        {
          $sample: {
            size: 1,
          },
        },
        {
          $project: {
            username: 1,
            profilepic: 1,  // Correct field name
          },
        },
      ]);

      console.log(randomUser[0].username)
      console.log(randomUser[0].profilepic)
  
      res.json(randomUser);
    } catch (err) {
      console.log(err);
      res.status(500).json({ error: err });
    }
  });

3

Answers


  1. you’re probably also need to check the statut from the response first, since the request can fails with a 404 or 500 HTTP error, fetch will fulfill the promise but the result may not be JSON, like this

    useEffect(() => {
        async function fetchUser() {
          try {
            const response = await fetch('http://10.0.2.2:3000/user');
            if(response.ok) {
                const data = await response.json();
                setUserData(data); // or data.data i don't know the structure from your api
            }
          } catch (error) {
            console.error(error);
          }
        }
        fetchUser();
      }, []);
    

    if the data you fetch was coming from an array of object it’s better to put a initial empty array like

    const [userData, setUserData] = useState([]);
    
    Login or Signup to reply.
  2. I think it might be because you are not accepting json value. Can you try in this way:

    import { StyleSheet, Text, View, Image } from 'react-native'
    import React, { useState, useEffect } from 'react'
    
    const SearchUserPage = () => {
      const [userData, setUserData] = useState();
    
      useEffect(() => {
          async function fetchUser() {
            fetch('http://10.0.2.2:3000/user', {
              method: 'GET',
              headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
              }
              body: JSON.stringify({city: 'London'}),
            }).then(response => {
              setUserData(response.json());
              return response.json();
            });
          }
    
          fetchUser();
        }, []);
    
      return (
        <View style={styles.container}>
          <View style={styles.userSection}>
            <View style={styles.imageContainer}>
              <Image
                style={styles.image}
                source={{ uri: userData.profilepic }}
                resizeMode="contain"
                overflow="hidden"
              />
            </View>
            <Text style={styles.text}>{userData.username}</Text>
          </View>
        </View>
      )
    }
    
    export default SearchUserPage
    
    Login or Signup to reply.
  3. import { StyleSheet, Text, View, Image } from 'react-native'
    import React, { useState, useEffect } from 'react'
    
    const SearchUserPage = () => {
      const [userData, setUserData] = useState();
    
      useEffect(() => {
        async function fetchUser() {
          try {
            const response = await fetch('http://10.0.2.2:3000/user');
            const data = response.json();
            setUserData(data);
          } catch (error) {
            console.error(error);
          }
        }
    
        fetchUser();
      }, []);
    
      // return null while waiting tor userData to load
      // you can return a spinner or "loading" text instead
      if (!userData) return null;
      
      return (
        <View style={styles.container}>
          <View style={styles.userSection}>
            <View style={styles.imageContainer}>
              <Image
                style={styles.image}
                source={{ uri: userData.profilepic }}
                resizeMode="contain"
                overflow="hidden"
              />
            </View>
            <Text style={styles.text}>{userData.username}</Text>
          </View>
        </View>
      )
    }
    
    export default SearchUserPage
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search