Skip to content

Commit 6eecf05

Browse files
authored
feat: supportNodeRef (#459)
* feat: supportNodeRef * chore: export
1 parent c374970 commit 6eecf05

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { default as useEvent } from './hooks/useEvent';
22
export { default as useMergedState } from './hooks/useMergedState';
3-
export { useComposeRef } from './ref';
3+
export { supportNodeRef, supportRef, useComposeRef } from './ref';
44
export { default as get } from './utils/get';
55
export { default as set } from './utils/set';
66
export { default as warning } from './warning';

src/ref.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable no-param-reassign */
22
import type * as React from 'react';
3-
import { isMemo } from 'react-is';
3+
import { isValidElement, ReactNode } from 'react';
4+
import { isFragment, isMemo } from 'react-is';
45
import useMemo from './hooks/useMemo';
56

67
export function fillRef<T>(ref: React.Ref<T>, node: T) {
@@ -56,4 +57,16 @@ export function supportRef(nodeOrComponent: any): boolean {
5657

5758
return true;
5859
}
60+
61+
export function supportNodeRef(node: ReactNode): boolean {
62+
if (!isValidElement(node)) {
63+
return false;
64+
}
65+
66+
if (isFragment(node)) {
67+
return false;
68+
}
69+
70+
return supportRef(node);
71+
}
5972
/* eslint-enable */

tests/ref.test.js renamed to tests/ref.test.tsx

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
/* eslint-disable no-eval */
22
import { fireEvent, render } from '@testing-library/react';
3-
import React from 'react';
3+
import React, { ReactNode } from 'react';
44
import useEvent from '../src/hooks/useEvent';
5-
import { composeRef, supportRef, useComposeRef } from '../src/ref';
5+
import {
6+
composeRef,
7+
supportNodeRef,
8+
supportRef,
9+
useComposeRef,
10+
} from '../src/ref';
611

712
describe('ref', () => {
813
describe('composeRef', () => {
@@ -12,7 +17,7 @@ describe('ref', () => {
1217

1318
const mergedRef = composeRef(refFunc1, refFunc2);
1419
const testRefObj = {};
15-
mergedRef(testRefObj);
20+
(mergedRef as any)(testRefObj);
1621
expect(refFunc1).toHaveBeenCalledWith(testRefObj);
1722
expect(refFunc2).toHaveBeenCalledWith(testRefObj);
1823
});
@@ -25,7 +30,7 @@ describe('ref', () => {
2530

2631
it('useComposeRef', () => {
2732
const Demo = ({ ref1, ref2 }) => {
28-
const mergedRef = useComposeRef(ref1, ref2);
33+
const mergedRef = useComposeRef<HTMLDivElement>(ref1, ref2);
2934
return <div ref={mergedRef} />;
3035
};
3136

@@ -70,14 +75,14 @@ describe('ref', () => {
7075
});
7176

7277
describe('supportRef', () => {
73-
class Holder extends React.Component {
78+
class Holder extends React.Component<{ children: ReactNode }> {
7479
render() {
7580
return this.props.children;
7681
}
7782
}
7883

7984
it('function component', () => {
80-
const holderRef = React.createRef();
85+
const holderRef = React.createRef<Holder>();
8186

8287
function FC() {
8388
return <div />;
@@ -93,7 +98,7 @@ describe('ref', () => {
9398
});
9499

95100
it('arrow function component', () => {
96-
const holderRef = React.createRef();
101+
const holderRef = React.createRef<Holder>();
97102

98103
// Use eval since jest will convert arrow function to function
99104
const FC = eval('() => null');
@@ -107,7 +112,7 @@ describe('ref', () => {
107112
});
108113

109114
it('forwardRef function component', () => {
110-
const holderRef = React.createRef();
115+
const holderRef = React.createRef<Holder>();
111116

112117
const FRC = React.forwardRef(() => <div />);
113118
render(
@@ -120,7 +125,7 @@ describe('ref', () => {
120125
});
121126

122127
it('class component', () => {
123-
const holderRef = React.createRef();
128+
const holderRef = React.createRef<Holder>();
124129

125130
class CC extends React.Component {
126131
state = {};
@@ -139,7 +144,7 @@ describe('ref', () => {
139144
});
140145

141146
it('memo of function component', () => {
142-
const holderRef = React.createRef();
147+
const holderRef = React.createRef<Holder>();
143148

144149
const FC = () => <div />;
145150
const MemoFC = React.memo(FC);
@@ -153,7 +158,7 @@ describe('ref', () => {
153158
});
154159

155160
it('memo of forwardRef function component', () => {
156-
const holderRef = React.createRef();
161+
const holderRef = React.createRef<Holder>();
157162

158163
const FRC = React.forwardRef(() => <div />);
159164
const MemoFC = React.memo(FRC);
@@ -166,4 +171,20 @@ describe('ref', () => {
166171
expect(supportRef(holderRef.current.props.children)).toBeTruthy();
167172
});
168173
});
174+
175+
describe('nodeSupportRef', () => {
176+
it('invalid element but valid ReactNode', () => {
177+
expect(supportNodeRef(true)).toBeFalsy();
178+
expect(supportNodeRef('div')).toBeFalsy();
179+
expect(supportNodeRef(123)).toBeFalsy();
180+
expect(supportNodeRef(<></>)).toBeFalsy();
181+
});
182+
183+
it('FC', () => {
184+
const FC = () => <div />;
185+
const RefFC = React.forwardRef(FC);
186+
expect(supportNodeRef(<FC />)).toBeFalsy();
187+
expect(supportNodeRef(<RefFC />)).toBeTruthy();
188+
});
189+
});
169190
});

0 commit comments

Comments
 (0)