dequelabs / dequelabs/cauldron

Bug: useSharedRef leaves a stale element reference on the parent ref after unmount

Open
#2,358 0 comments 0 reactions 1 assignee Claimed by @chornonoh-vova View on GitHub
Dominant language
TypeScript
Stars
127
Forks
31
Avg merge
2d 12h
Merged PRs (30d)
8

Description

## Problem

`useSharedRef` ([packages/react/src/utils/useSharedRef.ts](https://github.com/dequelabs/cauldron/blob/develop/packages/react/src/utils/useSharedRef.ts)) forwards the internal element to the parent ref via a `useEffect` keyed on `[ref]`, but it has no cleanup. When the host component unmounts, React clears the internal `MutableRefObject`, but the *parent's* ref is never updated — so a parent holding a function ref or a `MutableRefObject` is left pointing at the now-detached DOM node.

A class-style inline ref callback (`ref={(el) => setRef(parent, el)}`) gets called with `null` on unmount and forwards that to the parent. `useSharedRef` does not.

## Impact

Any consumer that uses `toastRef` / `drawerRef` / `dialogRef` / etc. for lifecycle tracking (e.g., `if (ref.current) { … }`) gets a falsy-positive after unmount — `ref.current` is truthy but points at a detached node. The bug compounds for components with portal logic or that conditionally mount, where consumers expect ref-clearing as a signal.

This affects every component that uses `useSharedRef` today: Toast, Drawer, Dialog, Combobox, Listbox, AnchoredOverlay, LoaderOverlay, CopyButton, TextEllipsis, and ComboboxOption.

## Proposal

Add a cleanup that propagates `null` to the parent ref on unmount:

```ts
export default function useSharedRef(ref: Ref): MutableRefObject {
const internalRef = useRef();
useEffect(() => {
setRef(ref, internalRef.current);
return () => setRef(ref, null);
}, [ref]);
return internalRef as MutableRefObject;
}
```

Add a test in `useSharedRef.test.tsx` that unmounts and asserts the external ref reads `null`.

## Surfacing

Surfaced during review of #2349 and originally raised by Copilot on that PR.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.