0

I'm trying to make a Rick & Morty API call with fetch and an async arrow function, but I found that the function is pushing the elements received twice into my array. I already tried to make the call with and without useEffect (I'm using React with TypeScript) but I got no results and I don't understand why the function is being called twice.

Anyone available to explain to me why this is happening?

data.ts:

import { PlanetInterface, ResidentsInterface } from "./data-interfaces";

export const planetsList: PlanetInterface[] = [];
export const residentsList: ResidentsInterface[] = [];

export const getPlanetById = async (planets: number[]) => {
  for (let planet of planets) {
    const response = await fetch(
      `https://rickandmortyapi.com/api/location/${planet}`
    );
    const planetData: PlanetInterface = await response.json();
    planetsList.push(planetData);
  }
  console.log(planetsList);
};

// export const getResidentsByPlanet = async (residents: string[]) => {
//   for (let resident of residents) {
//     const response = await fetch(resident);
//     const residentData = await response.json();
//     residentsList.push(residentData);
//   }
//   console.log(residentsList);
// };


app.tsx:

import { useEffect } from "react";
import { getPlanetById } from "./api/data";
import "./App.css";

function App() {
  useEffect(() => {
    getPlanetById([1, 2]);
  }, []);

  // getPlanetById([1, 2]);

  return <main className="container"></main>;
}

export default App;

Expected output: Array of 2 objects (planets with ID 1 and 2)

Received output: Array of 4 objects (planet with ID 1 twice and planet with ID 2 also twice)

If anyone can help me understand why this is happening and how I can fix it, I would be very grateful.

Ken White
  • 123,280
  • 14
  • 225
  • 444
Joacco
  • 3
  • 2
  • 1
    Sorry, but why dont you just declare `planetsList` inside of the function, for example, and return it as a result? Any reasons to keep it as a global variable? – Sergey Sosunov Feb 14 '23 at 01:25
  • No reason! It worked! I yet don't understand why it worked when declared inside of the function though... Thank you! – Joacco Feb 14 '23 at 01:41
  • It works because it's using a fresh array every time you run the function. Otherwise it accumulated values (2, then 4, then 6,etc). – Jorge Pérez Feb 14 '23 at 01:51

2 Answers2

0

I guess you are using <React.StrictMode />

If you remove that, the function is called once as you expect.

Here is the document about strict mode https://en.reactjs.org/docs/strict-mode.html

kyun
  • 9,710
  • 9
  • 31
  • 66
0

The design of that getPlanetById might be not suit for React since the call of it create a side effect and there is no way to clean it up, you should wrap it into a hook or do a manually clean up, here is an example:

useEffect(() => {
    getPlanetById([1, 2]);
    return () => { planetsList.length = 0 }
}, []);
Jerryh001
  • 766
  • 2
  • 11