From a31046370da4a9fcea4f6c110ca2886cbee6c492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Fri, 7 Feb 2025 18:15:30 +0800 Subject: [PATCH] fix: startTransition dead loop --- src/hooks/useNotification.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hooks/useNotification.tsx b/src/hooks/useNotification.tsx index 783b72b..6b5946a 100644 --- a/src/hooks/useNotification.tsx +++ b/src/hooks/useNotification.tsx @@ -155,12 +155,26 @@ export default function useNotification( } }); + // https://github.com/ant-design/ant-design/issues/52590 + // React `startTransition` will run once `useEffect` but many times `setState`, + // So `setTaskQueue` with filtered array will cause infinite loop. + // We cache the first match queue instead. + let oriTaskQueue: Task[]; + let tgtTaskQueue: Task[]; + // React 17 will mix order of effect & setState in async // - open: setState[0] // - effect[0] // - open: setState[1] // - effect setState([]) * here will clean up [0, 1] in React 17 - setTaskQueue((oriQueue) => oriQueue.filter((task) => !taskQueue.includes(task))); + setTaskQueue((oriQueue) => { + if (oriTaskQueue !== oriQueue || !tgtTaskQueue) { + oriTaskQueue = oriQueue; + tgtTaskQueue = oriQueue.filter((task) => !taskQueue.includes(task)); + } + + return tgtTaskQueue; + }); } }, [taskQueue]);