Showing data from state variable in ReactJS forms infinite loop

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!

Answer

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>
      ))}
    </>
  );
};