javascriptreactjsasynchronousreact-hookssetstate

How to make different state updates synchronous in React


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?


Solution

  • 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];