Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6428

React: How to handle cycle dependencies on useEffect

$
0
0

I have a React hook that receives a list of file URLs, which it downloads and saves into a local cache. The challenge I face is that I cannot figure out a good way to listen for changes in the cacheQueue state. When a new item is added to the cacheQueue, I would like to receive it in the useEffect and submit it to the cacheQueue. However, the challenge is that I make some changes to the cacheQueue within the useEffect to reflect the item's cache state, and this creates a cycle that goes on forever. How can I write my useEffect to avoid this endless loop?

  const useExternalCache = () => {const [filePath, setFilePath] = useState('');const [cacheQueue, setCacheQueue] = useImmer<CacheQueue[]>([]);const handleAdd = useCallback((queueItem: CacheQueue) => {  setCacheQueue((draft) => {    if (!draft.find((item) => item.uri === queueItem.uri)) {      draft.push(queueItem);    }  });}, []);const handleAddAll = useCallback(  (queueItems: CacheQueue[]) => {    setCacheQueue((draft) => {      const unique = Lodash.xorBy(queueItems, draft, 'uri');      if (!Lodash.isEqual(unique, draft)) {        unique.forEach(handleAdd);      }    });  },  [handleAdd],);const updateCacheQueueItem = useCallback((update: CacheQueue) => {  setCacheQueue((draft: CacheQueue[]) => {    const toUpdate = draft.find((item) => update.uri === item.uri);    if (toUpdate) {      const idx = draft.indexOf(toUpdate);      const current = draft[idx];      draft[idx] = {...current, ...update};    }  });}, []);const clearQueue = useCallback(() => {  setCacheQueue((draft: CacheQueue[]) => {    draft.splice(0, draft.length);  });}, []);const onAddToQueueDone = async ({  id: uri,  result,}: {  id: string;  result?: Promise<string>;}) => {  const cacheURI = await result;  cacheURI && setFilePath(cacheURI);};const addItemsToCacheQueue = useAsyncQueue({  concurrency,  done: onAddToQueueDone,});const getPathByUri = useMemo(  () => async (uri: string, headers?: any) => {    const result = await cache.getPathByUri(uri, headers);    if (result) {      const updatedUri =        Platform.OS === 'android' ? 'file://'+ result : result;      return updatedUri;    }    return result;  },  [],);const addToCacheQueue = useCallback(  ({uri, headers}: CacheQueue) =>    addItemsToCacheQueue.add({      id: uri,      task: async () => {        //Update item to reflect it is in caching queue        updateCacheQueueItem({          uri,          isCaching: true,        });        const result = await getPathByUri(uri, headers);        //Update item to reflect it is cached        updateCacheQueueItem({          uri,          isCaching: false,          isCached: true,        });        return result;      },    }),  [addItemsToCacheQueue, updateCacheQueueItem],);useEffect(() => {  console.log('cacheQueue changed: ', cacheQueue);  const newlyAdded = Lodash.filter(    cacheQueue,    ({isCaching, isCached}) => !(isCaching || isCached),  );  console.log('BgetPathByUri: adding', newlyAdded.length);  Lodash.forEach(newlyAdded, (item) => addToCacheQueue(item));}, [cacheQueue]);return {handleAddAll, filePath, getPathByUri};

};


Viewing all articles
Browse latest Browse all 6428

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>