简体   繁体   中英

React - update multiple useEffect / useCallback dependencies but only call effect once

I have a paginated list of data that I am updating based on a filter and an offset (page) When the offset is updated (next/prev page) I hit the API and get new data. When the filter is updated I reset the offset to 0.

The problem is, when the filter is updated and the offset is updated it causes the useEffect to be fired twice. Which in turn calls the api twice.

const [filter, setFilter] = useState('All');
const [offset, setOffset] = useState(0);
onFilterChange = (value) => {
  setFilter(value);
  offset !== 0 && setOffset(0);
}

getDataFromAPI = useCallback(() => {
   const endpoint = `https://example.com/data?filter=${filter}&offset=${offset}`;
   CallApi(endpoint);
}, [offset, filter])

useEffect(getDataFromAPI, [getDataFromAPI]);

I think the fix would be to get rid of useEffect in such case. Sometimes it is used needlessly. Just call CallApi inside the onFilterChange and onOffsetChange handlers with the new values that were set, and that's it.

Here are some relevant quotes from Dan Abramov:

In hindsight, my personal conviction has become that if some effect can't safely over-fire (eg fire twice instead of once), there is a problem. Usually things that can't over-fire are related to user actions ("buy", "send", "finish"). Actions start in event handlers. Use them!

To sum up, if something happens because a user did something, useEffect might not be the best tool.

On the other hand, if an effect merely synchronizes something (Google Map coordinates on a widget) to the current state, useEffect is a good tool. And it can safely over-fire.


PS But just to note I thought in your case react would batch the two different set state calls inside the filter change handler (hence call render once), but it seems it doesn't? In any case you may still prefer the recommendation in the beginning of my answer to remove useEffect .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM