diff --git a/CHANGELOG.md b/CHANGELOG.md index 21bdf11..eecdb85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,16 @@ ## [Unreleased] ### Changed -- Do not useLayoutEffect which shows warning in SSR +- Fix useAsyncCombineRace which was totally broken in v3.8.0 +- Do not useLayoutEffect which shows warning in SSR (#35) ## [3.8.0] - 2019-11-26 ### Changed - Fix inifinite loop in edge cases by avoiding slow memoization - Fix useAsyncRun for some cases with conditional running - Fix typings which are broken in #31 - - The state now has the aborted flag. - - This is technically a breaking change, but releasing it as a minor update. + - The state now has the aborted flag + - This is technically a breaking change, but releasing it as a minor update - Fix typings around Args ## [3.7.0] - 2019-11-09 @@ -72,7 +73,7 @@ ## [2.1.0] - 2019-04-16 ### Changed -- Fix a fatal bug in type definition. +- Fix a fatal bug in type definition - Update dependencies (incl. core-js@3) ## [2.0.0] - 2019-03-21 @@ -89,7 +90,7 @@ ## [1.2.0] - 2019-02-23 ### Changed - Rename useMemoSafe to useMemoPrev - - Although this is technically a breaking change, we release it as a minor update. + - Although this is technically a breaking change, we release it as a minor update ## [1.1.0] - 2019-02-18 ### Changed diff --git a/src/use-async-combine-race.js b/src/use-async-combine-race.js index 472fcfa..8ff211d 100644 --- a/src/use-async-combine-race.js +++ b/src/use-async-combine-race.js @@ -1,9 +1,24 @@ -import { useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; -import { useAsyncCombineAll } from './use-async-combine-all'; +import { useAsyncTask } from './use-async-task'; +import { useMemoList } from './utils'; export const useAsyncCombineRace = (...asyncTasks) => { - const task = useAsyncCombineAll(...asyncTasks); + const memoAsyncTasks = useMemoList(asyncTasks, (a, b) => a.start === b.start); + const task = useAsyncTask(useCallback( + async (abortController) => { + abortController.signal.addEventListener('abort', () => { + memoAsyncTasks.forEach((asyncTask) => { + asyncTask.abort(); + }); + }); + // start everything + memoAsyncTasks.forEach((asyncTask) => { + asyncTask.start(); + }); + }, + [memoAsyncTasks], + )); const finishedIndex = asyncTasks.findIndex(({ pending }) => !pending); useEffect(() => { // if there's one task finished, abort all the others @@ -15,5 +30,28 @@ export const useAsyncCombineRace = (...asyncTasks) => { }); } }); - return task; + const taskAborted = asyncTasks.every(({ aborted }) => aborted); + const taskPending = asyncTasks.every(({ pending }) => pending); + const taskError = asyncTasks.find(({ error }) => error); + const taskErrorAll = useMemoList(asyncTasks.map(({ error }) => error)); + const taskResult = useMemoList(asyncTasks.map(({ result }) => result)); + return useMemo(() => ({ + start: task.start, + abort: task.abort, + started: task.started, + aborted: taskAborted, + pending: taskPending, + error: taskError, + errorAll: taskErrorAll, + result: taskPending ? null : taskResult, + }), [ + task.start, + task.abort, + task.started, + taskAborted, + taskPending, + taskError, + taskErrorAll, + taskResult, + ]); };