Alexandre Paiva
Alexandre Paiva

Reputation: 1553

I cannot collect data from API using Axios + React

I'm beginner with React. I have 2 different cases where I'm using React Hooks which I cannot receive the data from my local API properly.

Case 1:

    export const RegisterT = () => {

        const [test, setTest] = useState()

        const addrState = {}

        axios.get('http://127.0.0.1:3333/states', { addrState })
         .then(res => {

            setTest(res.data)

            console.log(test)

        })

    ...

    }

It works with the state test displaying correctly the content from the API but I don't know why/how the Axios continues calling the API infinity - endless. (Ps: the very first call it returns undefined, then the next ones it works) What am I doing wrong?

To fix this I've tried to use useEffect like this (Case 2):

export const RegisterT = () => {

    const [test, setTest] = useState()

    const addrState = {}

    useEffect(() => {

        axios.get('http://127.0.0.1:3333/states', { addrState })
            .then(res => {

                setTest(res.data)

                console.log(test);

            })

    }, [])

...

}

Now the Axios works only once but no data is coming from the API. Maybe I should use async/wait for this case but I cannot make it work. Does anyone know how to fix that (Case 1 or/and Case 2)?

Thanks.

Upvotes: 0

Views: 65

Answers (2)

Sushanth --
Sushanth --

Reputation: 55750

Updating the state is an asynchronous operation. So the state is not really updated until the next time the component gets rendered. If you want to capture the correct state, you can either console.log(res.data) or wrap that inside the useEffect hook with test as dependency.

export const RegisterT = () => {

    const [test, setTest] = useState()

    const addrState = {}

   // effect only runs when component is mounted
    useEffect(() => {
        axios.get('http://127.0.0.1:3333/states', { addrState })
            .then(res => {
                setTest(res.data);
            });

    }, []);
    
    // effect runs whenever value of test changes
    useEffect(() => {
        console.log(test);
    }, [test]); 

}

That way it is guaranteed that the console.log runs when the value of test is updated.

Also the reason the API request is invoked once is you have not mentioned anything in the dependency array. [] empty dependency array runs the effect when the component is mounted for the first time.

async/await is just a wrapper around Promise object. So they would behave similarly.

Upvotes: 2

Mateusz Krzyżanowski
Mateusz Krzyżanowski

Reputation: 582

The solution with useEffect is good. If you don't use it each render will call the request. This is the same if you put there console.log with any information. The reason why you don't see the data in the useEffect is that the value of the state is not updated in current render but in the next which is called by setter of the state. Move the console.log(test); after useEffect to see the data. On init it will be undefined but in the next render, it should contain the data from the request.

Upvotes: 1

Related Questions