Light Yagami
Light Yagami

Reputation: 1043

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?

Upvotes: 1

Views: 2014

Answers (4)

user28390378
user28390378

Reputation:

I tried this

const [data, setData] = useState(null);
const [isDataLoading, setIsDataLoading] = useState(true);
const fetchData = async () => {
setIsDataLoading(true);
await hugeDataFetch().then((_yourResponse) => {
setData({ ..._yourResponse });
setIsDataLoading(false);
});
}
useEffect(() => {
fetchData();
}, 
[aVariable]);

return [isDataLoading, data];

Upvotes: 0

Dhruvil Mehta
Dhruvil Mehta

Reputation: 122

May Be this could work for you...! Simply need to check if your function is returning your data or not... If your returns something and is executed successfully then only it will update your response and set your state data.

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

Upvotes: 1

Bitrey
Bitrey

Reputation: 66

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

Upvotes: 1

Muhammad Jawad Mansoor
Muhammad Jawad Mansoor

Reputation: 348

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

Upvotes: 1

Related Questions