-1

I'm consuming an API using Axios in React, but when i come to set the response in a State so I may use the data, it is undefined. The funny thing is, if I put console.log inside Get.js I see the array perfectly. Am I returning the value the wrong way ?

PS: When I use console.log inside the Get.js,inside the 2nd .then, it prints two times the array. Why ?

MainPage.jsx

import { useEffect, useState } from 'react';
import { axiosGet } from '../../services/Get';
import { Header } from '../../components/Header/';
import { Welcome } from '../../components/Welcome/';

export const MainPage = () => {
  const [data, setData] = useState([]);
  useEffect(() => {
    console.log(axiosGet());
    setData(axiosGet());
  }, []);

  return (
    <>
      <Header />
      <Welcome />
      {data.length &&
        data.map(obj => {
        <p key={obj.id}>obj.name</p>;
    })}
    </>
  );

Get.js

import axios from 'axios';

export function axiosGet() {
  axios
    .get(
      `https://api.rawg.io/api/games?key=a6a08e14b07f41d09e846ec3c01e5db0&dates=2019-10-10,2022-03-01&page=2`
    )
    .then(res => {
      return res.data.results;
    })
    .then(arr => {
      return arr;
    })
    .catch(err => {
      console.error('oops! error: ' + err);
    });
}

if I change the Get.js code at this piece of code:

.then(res => {
          return res.data.results;
        })
        .then(arr => {
          console.log(arr)
          return arr;
        })

I got this:

Array(20) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
​
0: Object { slug: "forza-horizon-5", name: "Forza Horizon 5", playtime: 11, … }
​
1: Object { slug: "call-of-duty-modern-warfare", name: "Call of Duty: Modern Warfare (2019)", playtime: 0, … }
​
2: Object { slug: "resident-evil-village", name: "Resident Evil: Village", playtime: 16, … }
​
3: Object { slug: "assassins-creed-valhalla", name: "Assassin's Creed Valhalla", playtime: 0, … }
​
4: Object { slug: "genshin-impact", name: "Genshin Impact", playtime: 0, … }
​
5: Object { slug: "mafia", name: "Mafia: Definitive Edition", playtime: 9, … }
​
6: Object { slug: "superhot-mind-control-delete", name: "SUPERHOT: MIND CONTROL DELETE", playtime: 2, … }
​
7: Object { slug: "valheim", name: "Valheim", playtime: 11, … }
​
8: Object { slug: "it-takes-two-2", name: "It Takes Two", playtime: 11, … }
​
9: Object { slug: "deep-rock-galactic", name: "Deep Rock Galactic", playtime: 6, … }
​
10: Object { slug: "risk-of-rain-2", name: "Risk of Rain 2", playtime: 7, … }
​
11: Object { slug: "tell-me-why", name: "Tell Me Why", playtime: 2, … }
​
12: Object { slug: "factorio", name: "Factorio", playtime: 17, … }
​
13: Object { slug: "ghostrunner", name: "Ghostrunner", playtime: 4, … }
​
14: Object { slug: "marvels-avengers", name: "Marvel’s Avengers", playtime: 14, … }
​
15: Object { slug: "mafia-iii-definitive-edition", name: "Mafia III: Definitive Edition", playtime: 0, … }
​
16: Object { slug: "guardians-of-the-galaxy", name: "Marvel's Guardians of the Galaxy", playtime: 8, … }
​
17: Object { slug: "need-for-speed-heat", name: "Need for Speed Heat", playtime: 3, … }
​
18: Object { slug: "marvels-spider-man-miles-morales", name: "Marvel's Spider-Man: Miles Morales", playtime: 0, … }
​
19: Object { slug: "streets-of-rage-4", name: "Streets of Rage 4", playtime: 4, … }
​
length: 20
​
<prototype>: Array []
Get.js:12:15
Maiky
  • 126
  • 9
  • does not your `useEffect` keeps running that seems to be the issue to me, wrap it with empty array ...cause you need to load data one time `useEffect(()=> your get call, [])` – Anuj May 02 '22 at 18:11
  • Also, you are doing data.map while data may not even be there so better to check `data.length && data.map` – Anuj May 02 '22 at 18:13
  • `Uncaught TypeError: data is undefined`, I did the two changes you suggest. – Maiky May 02 '22 at 18:16
  • your useEffect useEffect(() => { console.log(axiosGet()); setData(axiosGet()); }); your map function {data.length && data.map(obj =>

    obj.name

    ;)} your map is incorrect :)
    – Anuj May 02 '22 at 18:17
  • can you provide console.log of your get call please ? probably it is nested inside another prop or something hence giving you undefined – Anuj May 02 '22 at 18:19
  • you don't need obj =

    ... just `{data.map(obj =>

    {obj.name}

    )}`
    – Anuj May 02 '22 at 18:21
  • I edited my question Anuj, take a look – Maiky May 02 '22 at 18:23
  • please change your map too – Anuj May 02 '22 at 18:24
  • it's done Anuj. – Maiky May 02 '22 at 18:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/244408/discussion-between-anuj-and-maiky). – Anuj May 02 '22 at 18:30

2 Answers2

2

The function axios.get() returns a Promise of the data you want. You need to modify your code to return this promise to the calling function:

export function axiosGet() {
  return axios
   .get(
      `https://api.rawg.io/api/games?key=a6a08e14b07f41d09e846ec3c01e5db0&dates=2019-10-10,2022-03-01&page=2`
    )

And then you need to await for an answer (to go from a Promise to the data):

useEffect(async () => {
  console.log(await axiosGet());
  setData(await axiosGet());
}, []);
Binary Brain
  • 1,170
  • 8
  • 20
1

The problem is that axiosGet doesn't actually return anything.

You can't though get it to directly return the API data, since that is only retrieved asynchronously. See this question for lots of discussion as to how to get the response from asynchronous requests and use it in your code.

In your case probably the easiest solution is to have axiosGet return the promise that axios.get (and your subsequent .then calls from it) gives you, and then await that in your useEffect so that you can set the state in your component to it.

So I would make the following changes:

First add the return statement to axiosGet:

export function axiosGet() {
  return axios
    .get(
      `https://api.rawg.io/api/games?key=a6a08e14b07f41d09e846ec3c01e5db0&dates=2019-10-10,2022-03-01&page=2`
    )
    .then(res => {
      return res.data.results;
    })
    .then(arr => {
      return arr;
    })
    .catch(err => {
      console.error('oops! error: ' + err);
    });
}

and adjust the useEffect in your component as follows:

useEffect(async () => {
  const apiData = await axiosGet();
  setData(apiData);
}, []);
Robin Zigmond
  • 17,805
  • 2
  • 23
  • 34