Created
January 11, 2021 11:41
-
-
Save tomhicks/95d455186fadda2f7d99e6163aa9d360 to your computer and use it in GitHub Desktop.
React Hook for queueing and processing async tasks sequentially
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function useTaskQueue(params: { | |
shouldProcess: boolean | |
}): { | |
tasks: ReadonlyArray<Task> | |
isProcessing: boolean | |
addTask: (task: Task) => void | |
} { | |
const [queue, setQueue] = React.useState<{ | |
isProcessing: boolean | |
tasks: Array<Task> | |
}>({isProcessing: false, tasks: []}) | |
React.useEffect(() => { | |
if (!params.shouldProcess) return | |
if (queue.tasks.length === 0) return | |
if (queue.isProcessing) return | |
const task = queue.tasks[0] | |
setQueue((prev) => ({ | |
isProcessing: true, | |
tasks: prev.tasks.slice(1), | |
})) | |
Promise.resolve(task()).finally(() => { | |
setQueue((prev) => ({ | |
isProcessing: false, | |
tasks: prev.tasks, | |
})) | |
}) | |
}, [queue, params.shouldProcess]) | |
return { | |
tasks: queue.tasks, | |
isProcessing: queue.isProcessing, | |
addTask: React.useCallback((task) => { | |
setQueue((prev) => ({ | |
isProcessing: prev.isProcessing, | |
tasks: [...prev.tasks, task], | |
})) | |
}, []), | |
} | |
} | |
type Task = () => Promise<void> | void |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @majames, I just double-checked this in my codebase. I noticed that I can remove the
flushSync(...)
now and the original problem is not reproducible.However, I was able to reproduce the problem on the code revision from a year ago... It could indeed be fixed by applying the
flushSync(...)
wrapper... It doesn't make a lot of sense to me. I'm assuming it has something to do with the context of my code and maybe some dependency constellation 🤷You're probably right that this is not the correct way to do this.