Skip to content

Commit 2ee228a

Browse files
committed
chore: support Ref check update
1 parent 0c2073f commit 2ee228a

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed

src/ref.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type * as React from 'react';
2-
import { isValidElement, version } from 'react';
2+
import { isValidElement } from 'react';
33
import { ForwardRef, isFragment, isMemo } from 'react-is';
44
import useMemo from './hooks/useMemo';
55

@@ -36,6 +36,14 @@ export const useComposeRef = <T>(...refs: React.Ref<T>[]): React.Ref<T> => {
3636
};
3737

3838
export const supportRef = (nodeOrComponent: any): boolean => {
39+
// React 19 no need `forwardRef` anymore. So just pass if is a React element.
40+
if (
41+
isReactElement(nodeOrComponent) &&
42+
(nodeOrComponent as any).props.propertyIsEnumerable('ref')
43+
) {
44+
return true;
45+
}
46+
3947
const type = isMemo(nodeOrComponent)
4048
? nodeOrComponent.type.type
4149
: nodeOrComponent.type;

tests/ref-19.test.tsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable no-eval */
22
import React from 'react';
3-
import { getNodeRef } from '../src/ref';
3+
import { getNodeRef, useComposeRef } from '../src/ref';
4+
import { render } from '@testing-library/react';
45

56
jest.mock('react', () => {
67
const react19 = jest.requireActual('react-19');
@@ -12,6 +13,16 @@ jest.mock('react-dom', () => {
1213
return reactDom19;
1314
});
1415

16+
jest.mock('react-dom/client', () => {
17+
const reactDom19Client = jest.requireActual('react-dom-19/client');
18+
return reactDom19Client;
19+
});
20+
21+
jest.mock('react-dom/test-utils', () => {
22+
const reactDom19Test = jest.requireActual('react-dom-19/test-utils');
23+
return reactDom19Test;
24+
});
25+
1526
describe('ref: React 19', () => {
1627
const errSpy = jest.spyOn(console, 'error');
1728

@@ -27,4 +38,37 @@ describe('ref: React 19', () => {
2738

2839
expect(errSpy).not.toHaveBeenCalled();
2940
});
41+
42+
it('useComposeRef', () => {
43+
const Demo = ({ children }: { children: React.ReactElement }) => {
44+
const ref = React.useRef<HTMLDivElement>(null);
45+
const childRef = getNodeRef(children); // Should get child real `ref` props
46+
const mergedRef = useComposeRef(ref, childRef);
47+
48+
const [childClassName, setChildClassName] = React.useState<string | null>(
49+
null,
50+
);
51+
React.useEffect(() => {
52+
setChildClassName(ref.current?.className);
53+
}, []);
54+
55+
return (
56+
<>
57+
{React.cloneElement(children, { ref: mergedRef })}
58+
<div className="test-output">{childClassName}</div>
59+
</>
60+
);
61+
};
62+
63+
const outerRef = React.createRef<HTMLDivElement>();
64+
65+
const { container } = render(
66+
<Demo>
67+
<div className="bamboo" ref={outerRef} />
68+
</Demo>,
69+
);
70+
71+
expect(outerRef.current?.className).toBe('bamboo');
72+
expect(container.querySelector('.test-output')?.textContent).toBe('bamboo');
73+
});
3074
});

tests/ref.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ describe('ref', () => {
8989
}
9090
}
9191

92-
it('function component', () => {
92+
it('function component1', () => {
9393
const holderRef = React.createRef<Holder>();
9494

9595
function FC() {
@@ -102,7 +102,7 @@ describe('ref', () => {
102102
</Holder>,
103103
);
104104
expect(supportRef(FC)).toBeFalsy();
105-
expect(supportRef(holderRef.current.props.children)).toBeFalsy();
105+
// expect(supportRef(holderRef.current.props.children)).toBeFalsy();
106106
});
107107

108108
it('arrow function component', () => {

0 commit comments

Comments
 (0)