From 676780874a92676372e46adfa3bd4f6e8cfdecf3 Mon Sep 17 00:00:00 2001 From: Satoshi Qazi Muhammed Date: Sun, 11 Oct 2026 23:12:51 +0400 Subject: [PATCH] Mark a component mounted in a layout effect useIsMountedRef set its ref in a passive effect, which React runs some time after the commit. In between, the component is in the DOM and can be clicked while the ref still says it is not mounted, and useToggle drops the click. The Accounts page showed it: an "Account" click right after the page drew did not open the create modal. Under load in a spec this happened in one run out of five. A layout effect runs during the commit, before an event can reach the component; unmounting still clears the ref. --- packages/react-hooks/src/useIsMountedRef.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/react-hooks/src/useIsMountedRef.ts b/packages/react-hooks/src/useIsMountedRef.ts index b135c0f..d9b32b1 100644 --- a/packages/react-hooks/src/useIsMountedRef.ts +++ b/packages/react-hooks/src/useIsMountedRef.ts @@ -3,7 +3,7 @@ import type React from 'react'; -import { useEffect, useRef } from 'react'; +import { useLayoutEffect, useRef } from 'react'; import { createNamedHook } from './createNamedHook.js'; @@ -12,7 +12,10 @@ export type MountedRef = React.MutableRefObject; function useIsMountedRefImpl (): MountedRef { const isMounted = useRef(false); - useEffect((): () => void => { + // A layout effect runs while the component is committed, before the browser + // can deliver an event to it. A passive effect runs later, so a click that + // lands in between found the ref still false and was dropped. + useLayoutEffect((): () => void => { isMounted.current = true; return (): void => {