0

I'm trying to show data from an API call. The structure of the application looks like

MainComponent -> RefreshButton (this will fetch the data)

MainComponent -> ShowData (this will show the data that is being fetched)

MainComponent has a state userData that will store the response that was received from the API. Now the issue is, whenever I'm clicking the button, it is getting into an infinite loop of rendering and calls the API infinite times.

This is what the error shows:

Here is my MainComponent -

import React, { useEffect, useState } from "react";
import RefreshButton from "./RefreshButton";
import ShowData from "./ShowData";

const MainComponent = () => {
    const [userData, setUserData] = useState();

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

    return (
        <div>
            <p style={{ textAlign: "center" }}>Main Component</p>

            <RefreshButton setUserData={setUserData} />
            {userData && <ShowData userData={userData} />}
        </div>
    );
};

export default MainComponent;

Here is my RefreshButton component -

import React from "react";
import axios from "axios";

const RefreshButton = ({ setUserData }) => {
    const getData = () => {
        axios
            .get(`https://jsonplaceholder.typicode.com/todos`)
            .then((response) => {
                if (response.status === 200) setUserData(response.data);
            })
            .catch((err) => {
                console.log(err);
            });
    };

    return (
        <div className="button-container">
            <button className="fetch-data-button" onClick={() => getData()}>
                Fetch new data
            </button>
        </div>
    );
};

export default RefreshButton;

And here is my ShowData component -

import React from "react";

const ShowData = ({ userData }) => {
    console.log("Here", userData);
    return (
        <>
            {userData.map((info, idx) => (
                <div className="user-data" key={idx}>
                    {info}
                </div>
            ))}
        </>
    );
};

export default ShowData;

PS - I'm new to React and couldn't find a potential solution on this, there are several tutorials on how to fetch data from API calls and show it, but I wanted to know what I'm doing wrong here. Thanks in advance!

Ryan Le
  • 7,708
  • 1
  • 13
  • 23
  • You don't seem to do anything wrong here. It makes infite loop of calling the same request you mean? – Kostas Aug 31 '21 at 05:27
  • I checked the API you are using. It returns an array of objects. Those objects cannot be displayed directly using `{info}` in `ShowData`. You should use `{info.title}`, {info.id}`, etc. Other than that your code seems fine and does not seem to cause an infinite loop. – Akhil Aug 31 '21 at 05:33
  • You really should paste the error that youre getting. – Shahab Uddin Aug 31 '21 at 05:35
  • @Kostas yes! It was a render error. – akashmodak97 Aug 31 '21 at 05:36

2 Answers2

2

You might have misunderstood with the infinite loop error

It's actually a render error as being shown here:

To fix your render error, simply put an actual string variable in the {}

Because the response was an array of this object, so you can't simply render the whole object but need to pick an actual string variable inside:

[{
   "userId": 1,
   "id": 1,
   "title": "delectus aut autem",
   "completed": false
}],

Change to something like this:

const ShowData = ({ userData }) => {
  console.log("Here", userData);
  return (
    <>
      {userData.map((info, idx) => (
        <div className="user-data" key={idx}>
          {info.title}  // <-- Put a title here.
        </div>
      ))}
    </>
  );
};
Ryan Le
  • 7,708
  • 1
  • 13
  • 23
-2

Remove

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

This will reevaluate component whenever user data changes, which Leeds to call showData infinitely

Kavitha K T
  • 119
  • 8
  • In this case, a console log will only be written when there is change in userdata, and it will not call showData infinitely – RABI Aug 31 '21 at 05:36
  • `useEffect` is literally an "Effect" after any state/prop change but not causing any re-render – Ryan Le Aug 31 '21 at 05:37