Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,19 @@ export const supportNodeRef = <T = any>(
/**
* In React 19. `ref` is not a property from node.
* But a property from `props.ref`.
* To check if `props.ref` exist or fallback to `ref`.
* In < React 19, `ref` lives on the element itself (`element.ref`).
*/
export const getNodeRef: <T = any>(
node: React.ReactNode,
) => React.Ref<T> | null = node => {
if (node && isReactElement(node)) {
const ele = node as any;

// Source from:
// https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/getReactNodeRef/getReactNodeRef.ts
return ele.props.propertyIsEnumerable('ref') ? ele.props.ref : ele.ref;
// React 19: `ref` is a regular prop and reading `element.ref` triggers a
// deprecation warning, even when the prop is absent. Branch on the React
// major version to avoid touching `element.ref` on React 19+.
return ReactMajorVersion >= 19
? (ele.props.ref ?? null)
: (ele.ref ?? null);
}
return null;
};
10 changes: 10 additions & 0 deletions tests/ref-19.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ describe('ref: React 19', () => {
expect(errSpy).not.toHaveBeenCalled();
});

it('getNodeRef on element without ref does not access element.ref', () => {
// Regression: previous propertyIsEnumerable('ref') check fell back to
// `element.ref` for elements rendered without an explicit ref prop, which
// triggers React 19's "Accessing element.ref was removed" warning.
const node = <div className="no-ref" />;

expect(getNodeRef(node)).toBeNull();
expect(errSpy).not.toHaveBeenCalled();
});

it('useComposeRef', () => {
const Demo: React.FC<React.PropsWithChildren> = ({ children }) => {
const ref = React.useRef<HTMLDivElement>(null);
Expand Down