Home > other >  Mapping through Starwars API by planet Name in React
Mapping through Starwars API by planet Name in React

Time:10-27

I am currently trying to map through every planet in the star wars api and print out the individual planet name but I am stuck. API LINK (https://swapi.dev/)

Thankyou for any help or advice

I tried using axios and Use Effect but am not sure where my errors may be. Below is what i have in my AllPlanets React Component.

`

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

const AllPlanets = () => {
  const [data, setData] = useState("");

  useEffect(() => {
    axios
      .get(`https://swapi.dev/api/planets`)
      .then((res) => setData(res.data))
      .catch((error) => console.log(error));
  });

  return (
    <div>
      {data && (
        <div className="flex">
          {data.map((planet, idx) => (
            <p>{planet.name}</p>
          ))}
        </div>
      )}
    </div>
  );
};

export default AllPlanets;

`

CodePudding user response:

These are the needed fixes (see comments in code as well):

  • The API response contains the property results that has the actual list of planets
  • The useEffect needs an empty dependencies array to block it from running on each render, and creating an infinite loop
  • Each item in an rendered list needs a key with a unique value

const { useState, useEffect } = React;

const AllPlanets = () => {
  const [data, setData] = useState("");

  useEffect(() => {
    axios
      .get(`https://swapi.dev/api/planets`)
      .then(res => setData(res.data.results)) // get the results property from the res.data object
      .catch(error => console.log(error));
  }, []); // add a dependency array so you won't have an infinite loop

  return (
    <div>
      {data && (
        <div className="flex">
          {data.map(({ name }) => (
            // use the name as key
            <p key={name}>{name}</p>
          ))}
        </div>
      )}
    </div>
  );
};

ReactDOM
  .createRoot(root)
  .render(<AllPlanets />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.1.3/axios.min.js" integrity="sha512-0qU9M9jfqPw6FKkPafM3gy2CBAvUWnYVOfNPDYKVuRTel1PrciTj a9P3loJB j0QmN2Y0JYQmkBBS8W mbezg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="root"></div>

CodePudding user response:

If you console.log the result you'll notice it's not an array of planets. It's an object with this structure:

{ 
  count: 60
  next: "https://swapi.dev/api/planets/?page=2"
  previous: null
  results: Array(10)
}

So replace

  .then((res) => setData(res.data))

with

  .then((res) => setData(res.data.results))

Alternatively, if you want to use next and previous provided links, for pagination, keep data in the returned format and map its results instead:

   {data.results.map((planet, idx) => (
      <p>{planet.name}</p>
   ))}

... and also make use of the previous and next links.

Here's an example:
https://codesandbox.io/s/wizardly-dirac-k7r1ek?file=/src/App.js

  • Related