1
- /* eslint-disable react/require-default-props */
2
- /* eslint-disable react/forbid-prop-types */
3
- import React from 'react' ;
4
1
import { render } from '@testing-library/react' ;
5
- import propTypes from 'prop-types ' ;
2
+ import React from 'react ' ;
6
3
7
4
import useForkRef from './useForkRef' ;
8
5
@@ -18,10 +15,10 @@ afterEach(() => {
18
15
19
16
describe ( 'useForkRef' , ( ) => {
20
17
it ( 'returns a single ref-setter function that forks the ref to its inputs' , ( ) => {
21
- function Component ( props ) {
18
+ function Component ( props : { innerRef : React . RefObject < HTMLDivElement > } ) {
22
19
const { innerRef } = props ;
23
- const ownRef = React . useRef ( null ) ;
24
- const [ , forceUpdate ] = React . useState ( 0 ) ;
20
+ const ownRef = React . useRef < HTMLDivElement > ( ) ;
21
+ const [ , forceUpdate ] = React . useState ( true ) ;
25
22
React . useEffect ( ( ) => forceUpdate ( n => ! n ) , [ ] ) ;
26
23
27
24
const handleRef = useForkRef ( innerRef , ownRef ) ;
@@ -31,19 +28,18 @@ describe('useForkRef', () => {
31
28
) ;
32
29
}
33
30
34
- Component . propTypes = {
35
- innerRef : propTypes . any
36
- } ;
37
-
38
- const outerRef = React . createRef ( ) ;
31
+ const outerRef = React . createRef < HTMLDivElement > ( ) ;
39
32
render ( < Component innerRef = { outerRef } /> ) ;
40
33
41
- expect ( outerRef . current . textContent ) . toBe ( 'has a ref' ) ;
34
+ expect ( outerRef . current ? .textContent ) . toBe ( 'has a ref' ) ;
42
35
expect ( console . error ) . not . toHaveBeenCalled ( ) ;
43
36
} ) ;
44
37
45
38
it ( 'forks if only one of the branches requires a ref' , ( ) => {
46
- const Component = React . forwardRef ( function Component ( props , ref ) {
39
+ const Component = React . forwardRef < HTMLDivElement > ( function Component (
40
+ _ ,
41
+ ref
42
+ ) {
47
43
const [ hasRef , setHasRef ] = React . useState ( false ) ;
48
44
const handleOwnRef = React . useCallback ( ( ) => setHasRef ( true ) , [ ] ) ;
49
45
const handleRef = useForkRef ( handleOwnRef , ref ) ;
@@ -58,16 +54,26 @@ describe('useForkRef', () => {
58
54
} ) ;
59
55
60
56
it ( 'does nothing if none of the forked branches requires a ref' , ( ) => {
61
- const Outer = React . forwardRef ( function Outer ( props , ref ) {
57
+ const setRef = jest . fn ( ) ;
58
+
59
+ type OuterProps = {
60
+ children : React . ReactElement ;
61
+ } ;
62
+
63
+ const Outer = React . forwardRef < null , OuterProps > ( function Outer (
64
+ props ,
65
+ ref
66
+ ) {
62
67
const { children } = props ;
63
- const handleRef = useForkRef ( children . ref , ref ) ;
64
68
65
- return React . cloneElement ( children , { ref : handleRef } ) ;
66
- } ) ;
69
+ // TODO: Fix this test as reading ref from children is not allowed so not available on React types
70
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
71
+ // @ts -ignore
72
+ const handleRef = useForkRef ( children ?. ref , ref ) ;
73
+ setRef ( handleRef ) ;
67
74
68
- // TODO: Figure out how to make react/no-unused-prop-types happy with the children
69
- // eslint-disable-next-line react/no-unused-prop-types
70
- Outer . propTypes = { children : propTypes . element . isRequired } ;
75
+ return children ? React . cloneElement ( children , { ref : handleRef } ) : null ;
76
+ } ) ;
71
77
72
78
function Inner ( ) {
73
79
return < div /> ;
@@ -79,55 +85,56 @@ describe('useForkRef', () => {
79
85
</ Outer >
80
86
) ;
81
87
expect ( console . error ) . not . toHaveBeenCalled ( ) ;
88
+ expect ( setRef ) . toHaveBeenCalledWith ( null ) ;
82
89
} ) ;
83
90
84
91
describe ( 'changing refs' , ( ) => {
85
- function Div ( props ) {
86
- const { leftRef, rightRef, ...other } = props ;
92
+ function Div (
93
+ props : {
94
+ leftRef ?: React . Ref < HTMLDivElement > ;
95
+ rightRef ?: React . Ref < HTMLDivElement > ;
96
+ } & React . HTMLAttributes < HTMLDivElement >
97
+ ) {
98
+ const { leftRef = null , rightRef = null , ...other } = props ;
87
99
const handleRef = useForkRef ( leftRef , rightRef ) ;
88
100
89
101
return < div { ...other } ref = { handleRef } /> ;
90
102
}
91
103
92
- Div . propTypes = {
93
- leftRef : propTypes . oneOfType ( [ propTypes . func , propTypes . object ] ) ,
94
- rightRef : propTypes . oneOfType ( [ propTypes . func , propTypes . object ] )
95
- } ;
96
-
97
104
it ( 'handles changing from no ref to some ref' , ( ) => {
98
105
const { rerender } = render ( < Div id = 'test' /> ) ;
99
106
100
107
expect ( console . error ) . not . toHaveBeenCalled ( ) ;
101
108
102
- const ref = React . createRef ( ) ;
109
+ const ref = React . createRef < HTMLDivElement > ( ) ;
103
110
rerender ( < Div id = 'test' leftRef = { ref } /> ) ;
104
111
105
- expect ( ref . current . id ) . toBe ( 'test' ) ;
112
+ expect ( ref . current ? .id ) . toBe ( 'test' ) ;
106
113
expect ( console . error ) . not . toHaveBeenCalled ( ) ;
107
114
} ) ;
108
115
109
116
it ( 'cleans up detached refs' , ( ) => {
110
- const firstLeftRef = React . createRef ( ) ;
111
- const firstRightRef = React . createRef ( ) ;
112
- const secondRightRef = React . createRef ( ) ;
117
+ const firstLeftRef = React . createRef < HTMLDivElement > ( ) ;
118
+ const firstRightRef = React . createRef < HTMLDivElement > ( ) ;
119
+ const secondRightRef = React . createRef < HTMLDivElement > ( ) ;
113
120
114
121
const { rerender } = render (
115
122
< Div leftRef = { firstLeftRef } rightRef = { firstRightRef } id = 'test' />
116
123
) ;
117
124
118
125
expect ( console . error ) . not . toHaveBeenCalled ( ) ;
119
126
120
- expect ( firstLeftRef . current . id ) . toBe ( 'test' ) ;
121
- expect ( firstRightRef . current . id ) . toBe ( 'test' ) ;
127
+ expect ( firstLeftRef . current ? .id ) . toBe ( 'test' ) ;
128
+ expect ( firstRightRef . current ? .id ) . toBe ( 'test' ) ;
122
129
expect ( secondRightRef . current ) . toBe ( null ) ;
123
130
124
131
rerender (
125
132
< Div leftRef = { firstLeftRef } rightRef = { secondRightRef } id = 'test' />
126
133
) ;
127
134
128
- expect ( firstLeftRef . current . id ) . toBe ( 'test' ) ;
135
+ expect ( firstLeftRef . current ? .id ) . toBe ( 'test' ) ;
129
136
expect ( firstRightRef . current ) . toBe ( null ) ;
130
- expect ( secondRightRef . current . id ) . toBe ( 'test' ) ;
137
+ expect ( secondRightRef . current ? .id ) . toBe ( 'test' ) ;
131
138
} ) ;
132
139
} ) ;
133
140
} ) ;
0 commit comments