skip to Main Content

I have a component which has two state variables:

const [data, setData] = useState(null);
const [isDataLoading, setIsDataLoading] = useState(true);

const fetchData = async () => {
    setIsDataLoading(true);
    const fetchedHugeData = await hugeDataFetch();
    setData({ ...fetchedHugeData });
    setIsDataLoading(false);
}

useEffect(() => {
    fetchData();
},[aVariable]);

return [isDataLoading, data];

In the above code, the setIsDataLoading(false) is getting executed even before setData() finished in the previous line.

How can I make sure that not happen?

4

Answers


  1. You need to add another useEffect to view the data state.The code should look like this.

    const [data, setData] = useState(null);
    const [isDataLoading, setIsDataLoading] = useState(true);
    
    const fetchData = async () => {
        setIsDataLoading(true);
        const fetchedHugeData = await hugeDataFetch();
        setData({ ...fetchedHugeData });
      //  setIsDataLoading(false); 
    }
    
    useEffect(() => {
        fetchData();
    },[aVariable]);
    
    useEffect(() => {
        if (data !== null) { setIsDataLoading(false); }
    }, [data])
    
    
    return [isDataLoading, data];
    
    Login or Signup to reply.
  2. As ghybs said, state updates are asynchronous, therefore the best solution would be to use another useEffect that listens to data and, if not null, calls setIsDataLoading.

    const [data, setData] = useState(null);
    const [isDataLoading, setIsDataLoading] = useState(true);
    
    const fetchData = async () => {
        setIsDataLoading(true);
        const fetchedHugeData = await hugeDataFetch();
        setData({ ...fetchedHugeData });
    };
    
    useEffect(() => {
        fetchData();
    }, [aVariable]);
    
    useEffect(() => {
        if (data) {
            setIsDataLoading(false);
        }
    }, [data])
    
    return [isDataLoading, data];
    Login or Signup to reply.
  3. May Be this could work for you…!

    const [data, setData] = useState(null);
    const [isDataLoading, setIsDataLoading] = useState(true);
    
    const fetchData = async () => {
        setIsDataLoading(true);
        hugeDataFetch().then((_yourResponse) => {
            setData({ ..._yourResponse });
            setIsDataLoading(false);
        });
    }
    
    useEffect(() => {
        fetchData();
    }, [aVariable]);
    
    return [isDataLoading, data];
    
    Login or Signup to reply.
  4. To ensure that the state updates are executed synchronously in React, you can use the await keyword before calling setData() in the fetchData function. This will ensure that the state update is completed before moving on to the next line of code.

    Here’s the updated code with the await keyword:

    import React, { useState, useEffect } from 'react';
    
    const YourComponent = () => {
      const [data, setData] = useState(null);
      const [isDataLoading, setIsDataLoading] = useState(true);
    
      const fetchData = async () => {
        setIsDataLoading(true);
        const fetchedHugeData = await hugeDataFetch();
        await setData({ ...fetchedHugeData }); // Use await here
        setIsDataLoading(false);
      }
    
      useEffect(() => {
        fetchData();
      }, [aVariable]);
    
      return [isDataLoading, data];
    }
    

    By adding await before setData({ …fetchedHugeData }), the setIsDataLoading(false) will not be executed until the state update operation of setData is finished.

    Keep in mind that when using await within an async function, the function itself should be marked as async. In this case, the fetchData function is marked as async.

    With this change, the state updates will be executed synchronously, ensuring that setIsDataLoading(false) will not run until the state update operation of setData is completed.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search