Octavian Niculescu
Octavian Niculescu

Reputation: 1327

Axios get call returns undefined, even if I use async code

For this piece of code:

import { useEffect, useState } from 'react';

import 'ag-grid-community/dist/styles/ag-grid.min.css';
import 'ag-grid-community/dist/styles/ag-theme-material.min.css';
import Grid from '../Common/Grid';
import axios from 'axios';

function GetJudete() {
  axios.get("http://localhost:5266/api/judete").then((response) =>
  {
    let data = response.data;
    return data;
  } 
  ).catch(err => {
    console.log("Eroare la aducerea datelor.");      
  })
};

function Localitati()
{
  let judete;
  useEffect(() => {
    judete = GetJudete();
  }, []);
  console.log(judete);
  
  const [columnDefs] = useState([
    { field: 'nume', filter: 'agTextColumnFilter', editable: true },
    { field: 'judetID', filter: 'agTextColumnFilter', editable: true },
  ])
  return (
    <Grid 
    baseLink='http://localhost:5266/api/localitati'
    columnDefs={columnDefs}
    />
  );
}

export default Localitati;

my console.log() prints undefined. I expected it to be filled with values, because I'm using async code in GetJudete() by using Promises.

I see that it does not work this way though.

Why and how can I fix this?

Thanks.

Upvotes: 0

Views: 114

Answers (4)

MamadTvl
MamadTvl

Reputation: 1

You have 2 problems !

  1. data fetching :

GetJudete function must return a Promise so try :

async function GetJudete() {
    try {
        const response = await axios.get("http://localhost:5266/api/judete");
        let data = response.data;
        return data; 
    } catch (err) {
      console.error(err);
    }
};

  1. hooks data fetching:

useEffect callbacks are synchronous to prevent race conditions so we need to put async function inside the useEffect callback and also you should use states to do anything with your data other than that react don't know when something has changed to re-render component

useEffect(() => {
  const fetchData = async () => {
    const data = await GetJudete();
    console.log(data);
    // setState is required here !
    return data;
  }
  fetchData();
}, [])

Upvotes: 0

digitalbreed
digitalbreed

Reputation: 4070

There are two major reasons why you're seeing undefined:

  1. Code in useEffect is run after render. That's why any update to judete would happen after you already logged it. (Once it's set correctly, you would need to trigger a rerender in order to see a second log line.)

  2. Your GetJudete function doesn't return anything, that's why you still would be getting undefined. (Your promise does return something, but that's never used anywhere.)

Here's a way to work around both issues:

import { useEffect, useState } from 'react';

import 'ag-grid-community/dist/styles/ag-grid.min.css';
import 'ag-grid-community/dist/styles/ag-theme-material.min.css';
import Grid from '../Common/Grid';
import axios from 'axios';

async function GetJudete() {
    try {
        const { data } = await axios.get("http://localhost:5266/api/judete");
        return data;
    } catch (_) {
        console.log("Eroare la aducerea datelor.");      
    }
};

function Localitati()
{
  // Use a state instead of a local variable, so that React knows about updates
  const [judete, setJudete] = useState();

  useEffect(() => {
    async function getJudeteAsync() {
      const result = await GetJudete();
      setJudete(result);
    }
    // Trigger the async function from your effect
    getJudeteAsync();
  }, []);

  // The first render will yield "undefined";
  // once the AJAX call is successfully done, the setJudete above will cause a re-render and you should see a second log line with an actual value
  console.log(judete);
  
  const [columnDefs] = useState([
    { field: 'nume', filter: 'agTextColumnFilter', editable: true },
    { field: 'judetID', filter: 'agTextColumnFilter', editable: true },
  ])
  return (
    <Grid 
    baseLink='http://localhost:5266/api/localitati'
    columnDefs={columnDefs}
    />
  );
}

export default Localitati;

Upvotes: 1

PM75902693
PM75902693

Reputation: 71

You need to console.log data after it's resolved.

In your current code you are printing judetes when component is created. To fix your issue you should call console.log in .then since it's resolved some time after component creation.

Upvotes: 1

Mahmoud Ibrahiam
Mahmoud Ibrahiam

Reputation: 139

try this

async function getJudate(){
    await axios.get(...).then(...)
}
useEffect(() => {
    let judate = getJudate()
    console.log(judate)
}, [])

Upvotes: 1

Related Questions