Home > Blockchain >  My API is returning undefined instead of response value
My API is returning undefined instead of response value

Time:05-03

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

CodePudding user response:

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);
}, []);

CodePudding user response:

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());
}, []);
  • Related