0

I want to fetch all data in the JSON where there are two arrays. Rest of the data is correctly fetched, but when it comes to arrays I get "user.category is undefined" or "user.top_media is undefined". How can I fix this?

console.log(response) returns success if I delete HTML's in return statement.

import React from 'react';
import './influencerProfileCard.css';
import { useState, useEffect } from 'react';
import { InstagramEmbed } from 'react-social-media-embed';    

const InfluencerProfileCard = () => {

    const [user, setUser] = useState([]);

    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    const x = urlParams.get('influencer');    

    useEffect(() => {
      fetchUsers();
    }, []); 
  
    async function fetchUsers() {
        const response = await 
            fetch(`http://localhost:3001/api/tours/${x}`)
                .then((res) => res.json())
                .then((user) => user.data.tour)
    
      console.log(response);
      setUser(response);
    }

    return (
        <div className="infProfCard-container">

            <div className='infProfCard-info'>
                {user.category.map(c => (
                    <h4>{c}</h4>
                ))}
            </div>

            <div style={{ display: 'flex', justifyContent: 'center' }}>
                <InstagramEmbed url={user.top_media[0].media_url} width={328} captioned />
            </div>

            </div>
    )
}

export default InfluencerProfileCard

and here is the JSON file when I directly type the API on browser:

JSON response

here is the console output:

console output

9
  • Do you get the same output in the console as well? Commented Jan 7, 2023 at 16:08
  • have you tried "user.tour" instead of "user.data.tour" in then after fetch? Commented Jan 7, 2023 at 16:09
  • Base on the JSON file, looks like it should be .then((user) => user.tour) instead of .then((user) => user.data.tour) Commented Jan 7, 2023 at 16:11
  • I think you have a problem with the loading state. When the Promise is not yet resolved, you are already trying to access the properties, which are undefined at this moment. Commented Jan 7, 2023 at 16:13
  • @KostasMinaidis I've added the console output. user.tour prints console "undefined". Commented Jan 7, 2023 at 16:14

1 Answer 1

0

There is no issue with the data, however useState is asynchronous, so you need to include your setState in your fetch and await this state, otherwise React will try to render your page the state (which is empty[]) before you update your state with the data.

Update: you're probably also need to check the flag ok 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 :

const [user, setUser] = useState([]); // make sure the initial state is an empty array.
    
    useEffect(() => {
      fetchUsers();
    }, []); 
  
    async function fetchUsers() {
      try {
        const response = await fetch(`http://localhost:3001/api/tours/${x}`);
            if(!response.ok)
              throw new Error(`HTTP error ${response.status}`); 
              const user = await response.json() //parse to json only if the response statut is 200
            setUser(user.data.tour);
      } catch (err) {
        console.log(err)
      }
    };

you can also add a loading page, it will be a better user experience to see a loading screen, this is a simple example:

const [user, setUser] = useState([]); // make sure the initial state is an empty array.
const [loading, setLoading] = useState(false);
   
    useEffect(() => {
      async function fetchUsers() {
        setLoading(true);
      try {
        const response = await fetch(`http://localhost:3001/api/tours/${x}`);
            if(!response.ok)
              throw new Error(`HTTP error ${response.status}`); 
              const user = await response.json() 
              setUser(user.data.tour);
      } catch (err) {
        console.log(err)
      } finally {
        setLoading(false);
      }
     }
      fetchUsers();
    }, []); 

    if (loading) {
      return <h1>User is loading...</h1>;
    } 
    return (
      <div className="infProfCard-container">
          <div className='infProfCard-info'>
              {user.category.map(c => (
                  <h4>{c}</h4>
              ))}
          </div>
          <div style={{ display: 'flex', justifyContent: 'center' }}>
              <InstagramEmbed url={user.top_media[0].media_url} width={328} captioned />
          </div>
      </div>
    ) 
Sign up to request clarification or add additional context in comments.

11 Comments

I've tried this and user.category is still undefined.
hm we need to check the state from user in the component, how about user.top_media[0].media_url it's also undefined ? just in case i update my answer.
yes it is also undefined, they are not loaded most of the time and usually cause a white screen.
@questionhead when you said not most of the time you mean sometimes it load or never load at first rendering ?
sometimes it load but it happens like this: I open the page without the user.category.map function and Instagram embed in the html part. Then I put the map function in the html part and save the page and it renders strangely.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.