Search code examples
reactjsstrapi

React app calls a request in a loop when you open a page


I am working with Strapi, which is built on React. I have a custom page which I try to show some data. However, when I open that page, the network tab and the debugger on terminal, show that a request is triggered in a loop. Since I am new to React, I am not sure what the problem is, but my guess is something with the state.

  const { pathType, id } = useParams();
  const [data, setData] = useState([]);
  const getData = () => request(`/${pathType}/${id}`, {method: 'GET'});
 
  useEffect(() => {
    getData().then(response => {
      return response;
    }).then(setData).catch(e => console.log(e));
  });

  return (
    <>
      <Container className="container-fluid">
        <div className="row">
          {JSON.stringify(data, null, 2)}
        </div>
      </Container>
    </>
  );

And here is part of the debugger where shows the request from the getData()

[2020-08-31T10:33:30.644Z] debug OPTIONS /hostings/40 (1 ms) 204
[2020-08-31T10:33:30.942Z] debug GET /hostings/40 (297 ms) 200
[2020-08-31T10:33:30.949Z] debug OPTIONS /hostings/40 (0 ms) 204
[2020-08-31T10:33:31.241Z] debug GET /hostings/40 (291 ms) 200
....

Solution

  • Referring to react documentation on useEffect

    Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.

    Simply put: in your case, useEffect will be called every time you change the DOM through using setData

    Now you want your useEffect to only setData only when data is empty. To do that you should add a condition to the useEffect as follows:

    useEffect(() => {
      if (data.lenght !== 0) return
      getData().then(response => {
        return response;
      }).then(setData).catch(e => console.log(e));
    });
    

    This will ensure that you setData only when data is empty.


    You can check Why effects run on each update

    And "quoting from react docs"

    If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument.

    So useEffect should look like

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