1

I have some issue. When I do to async fetch data (using axios for fetching) in the useEffect, and after I set responsed data to state, using a useState hook. And page render befor then I got response from server. For demonstration this issue I have putted console.log for get current state, and I get 'undefined':

const [positions, setPositions] = useState([]);

useEffect(() => {
    const fetchPositions = async () => {
        const response = await EmployeeService.getEmployeePositions();
        setPositions(response.data);
    };
    
    fetchPositions();
    console.log('positions from state: ', positions); //undefined
}, []);

Method for fetching data from "EmployeeService":

getEmployeePositions(){
    return axios.get(EMPLOYEE_API_BASE_URL + '/positions');
}

Thanks in advance, and best regards!

andrew_savich
  • 33
  • 1
  • 7
  • that console.log would never log the result given that the result doesn't exist until the async function is done. `undefined` is the correct and expected result. – Kevin B Sep 28 '21 at 14:58
  • note that `setPositions` doesn't have immediate effect so it can be undefined https://stackoverflow.com/a/54069332/507203 – cjmling Sep 28 '21 at 15:50

2 Answers2

2

React needs to re-render to display the results. Which means you need to capture the result on the subsequent re-render that is caused when you setState. Move the console log outside of the useEffect

const [positions, setPositions] = useState([]);

useEffect(() => {
    const fetchPositions = async () => {
        const response = await EmployeeService.getEmployeePositions();
        setPositions(response.data);
    };

    fetchPositions();
}, []);

console.log('positions from state: ', positions); // NOT UNDEFINED

React will always render once before you have data. So you can catch it with a condition.

if (positions.length === 0) {
   return null;
}
Daniel Duong
  • 1,084
  • 4
  • 11
-1

nothing wrong with your code, useEffect is always undefined because it read the first value of your rendered app. To update state in useEffect put paramater on the array [] but in your case it will cause an infinity loop.

try logging inside the async function instead

const [positions, setPositions] = useState([]);

useEffect(() => {
    const fetchPositions = async () => {
        const response = await EmployeeService.getEmployeePositions();
        setPositions(response.data);
        console.log('data from response: ', response);
    };
    
    fetchPositions();
    
}, []);

or do it like this

const [positions, setPositions] = useState([]);

useEffect(() => {
    const fetchPositions = async () => {
        const response = await EmployeeService.getEmployeePositions();
        setPositions(response.data);
        console.log('data from response: ', response);
    };

    if((positions ?? []).length == 0){
    fetchPositions();
    console.log('this is position state before fetch~>',positions)
    } else{
    console.log('this is position state after fetch~>',positions)
    }
}, [positions]);
ucup
  • 665
  • 6
  • 17