From d20c3af9d11ea4a35bfc76cb44c15af9d42059c4 Mon Sep 17 00:00:00 2001 From: Luna Ruan Date: Fri, 6 May 2022 12:36:03 -0700 Subject: [PATCH] [DevTools][Bug] Fix Race Condition When Unmounting Fibers (#24510) When we delete fibers, we will call onCommitFiberUnmount on every deleted fiber to also remove them from the element tree. However, there are some cases where fibers aren't deleted but we still want to remove them from the element tree (ex. offscreen). In the second case, we recursively remove these children during handleCommitFiberRoot. When we remove an element, we will untrack its corresponding fiber ID. However, because of fast refresh, we don't do this immediately, opting to instead add the value to a set to process later. However, before the set has been processed, we unmount that fiber again, we will get duplicate unmounts. To fix this, handleCommitFiberRoot explicitly flushes all the fibers in the set before starting the deletion process. We also need to do this in handleCommitFiberUnmount in case handleCommitFiberRoot gets called first. --- packages/react-devtools-shared/src/backend/renderer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 5e09a2d0f804..055b57ee4b52 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -2630,6 +2630,10 @@ export function attach( } function handleCommitFiberUnmount(fiber) { + // Flush any pending Fibers that we are untracking before processing the new commit. + // If we don't do this, we might end up double-deleting Fibers in some cases (like Legacy Suspense). + untrackFibers(); + // This is not recursive. // We can't traverse fibers after unmounting so instead // we rely on React telling us about each unmount.