skip to Main Content

I can’t update the data in useEffect, even after using async.
Note: I don’t to add data as dependency in useEffect as I want to fetch data only once

import { useEffect, useState } from "react"

function RenderBody() {

    let [data, setData] = useState([])

    useEffect(() => {
        async function fetchData() {
            let response = await fetch('https://dummyjson.com/products/1')
            let responseJson = await response.json();
            console.log(responseJson);
            await setData((prevData) => {
                return {...prevData, responseJson}
            });
            console.log(data);
        }
        fetchData();
    }, []);
    
    return (
        <>
            {data.length > 0 ? data.map(element => {
                return <>
                    <div>{element.brand}</div>
                    <div>{element.price}</div>
                </>
            }) : <div>Nothing to display</div>}
        </>
    )
}

export default RenderBody ```

2

Answers


  1. I can’t update the data in useEffect

    Sure you can, and you are. But what are you updating it to? The state value is initially an array:

    let [data, setData] = useState([])
    

    And initially the UI doesn’t display anything because it checks the length property of the array:

    data.length > 0 ? ...
    

    Then you update state to an object:

    await setData((prevData) => {
        return {...prevData, responseJson}
    });
    

    Since this object has no length property, data.length is undefined. And undefined is not > 0, so the UI continues to successfully not display anything.

    Assuming responseJson is an object to be added to the array, it looks like you just want to spread into an array instead of an object:

    setData((prevData) => {
        return [...prevData, responseJson]
    });
    

    (Note also that I removed the await, since using await on something that isn’t awaitable is a no-op, so the keyword isn’t doing anything useful there.)


    As an aside… Since this effect only occurs once when the component first loads, and it’s known that the state value is empty, you can do without the prevData approach entirely and simplify:

    setData([responseJson]);
    

    Additionally… You can remove the console.log(data); on the line after updating state. This is just going to log an empty array to the console, and you already know the initial state was an empty array because it’s explicitly defined as such in the code.

    If you want to log the new state, that value is in responseJson, which you already logged.

    Login or Signup to reply.
  2. You setting the data to an object instead of an array.

      useEffect(() => {
            async function fetchData() {
                let response = await fetch('https://dummyjson.com/products/1')
                let responseJson = await response.json();
                console.log(responseJson);
                await setData((prevData) => {
                    return [...prevData, responseJson]
                });
                console.log(data);
            }
            fetchData();
        }, []);
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search