API response data is not visible

71 Views Asked by At

I am pulling some data from Facebook API,

const response = await axios.get('API ENDPOINT')
     setData(response.data); // Assuming the data is in the response.data
     console.log(response.data) //printing values
     console.log('Data copied to state:', data); // Log the state after update
     

console.log(response.data) This one logs data correctly as JSON object in console console.log('Data copied to state:', data) gives an empty array.

Accessed from HTML Element

{data?.length > 0 && (
      <ul>
        {data.map((item, index) => (
          <li key={index}>
            {/* Access item properties here */}
            {item.email} - {item.last_name}
          </li>
  ))}

How to get data populated to data object to print in HTML Element

4

There are 4 best solutions below

0
Kobra On

Setting state in React is asynchronous. This means the setData function doesn't immediately mutate the provided state but creates a pending state transition. This is the reason why you're seeing an empty array when you console log data immediately after setting it.

You may want to actually check the data in your render function or just after your useEffect hook if you have one.

Example:

useEffect(() => {
    const fetchData = async () => {
        const response = await axios.get('API ENDPOINT')
        setData(response.data);
    }
    fetchData();
}, []);

You're going to show the data on the component, so you can't use useRef, so using useEffect is the best way I can see.

check this video

0
hokwanhung On

@Kobra's answer answers the question - setState is asynchronous and might not reflect immediate changes of the state. And useEffect is a great tool to synchronous components (including state) with an external system.

As it is unclear how you use your function with the fetch() method; a way to check the changed value of a state is to put it in a useEffect, with dependencies specified. For example,

useEffect(() => {
    console.log(data);
}, [data])

// The result should be something like this with `dev` mode, if set correctly:
// <initial_value>
// <initial_value>
// <updated_value>

And the data should populate the HTML once the state is updated - React would re-render the component when state changes (according to React's documentation).

1
Jatin sharma On

The issue you're facing might be due to the asynchronous nature of the setData function call. When you log data immediately after calling setData, it may not have been updated yet.

Here's how you can adjust your code to ensure that data is populated correctly:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function YourComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('API ENDPOINT');
        setData(response.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();
  }, []); // Empty dependency array to ensure useEffect runs only once

  return (
    <div>
      {data.length > 0 ? (
        <ul>
          {data.map((item, index) => (
            <li key={index}>
              {/* Access item properties here */}
              {item.email} - {item.last_name}
            </li>
          ))}
        </ul>
      ) : (
        <p>No data available</p>
      )}
    </div>
  );
}

export default YourComponent;
0
iamsmruti On

@Kobra and @hokwanhung answered the question. I want to segregate both of the things.

const fetchData = async () => {
   const response = await axios.get('API ENDPOINT')
   setData(response.data);
}


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

useEffect(() => {
   console.log(data)
}, [data])

This is how you will get the data in the console.log(). Because setData() doesn't immediately populate the response.

Then you can use that value in data to render the HTML

{data?.map((item) => {
   {/* JSX */}
})}

I hope, putting it all together makes sense for you.