Skip to content

Commit 59246b6

Browse files
authored
fix(useMouseAndTouchTrackers): dependency array (#1612)
* fix(useMouseAndTouchTrackers): dependency array * remove console logs * some improvements * pass references
1 parent ee2a828 commit 59246b6

File tree

5 files changed

+151
-54
lines changed

5 files changed

+151
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`utils useMouseAndTouchTracker adds and removes listeners to environment: element change rerender adding events 1`] = `
4+
[
5+
[
6+
mousedown,
7+
[Function],
8+
],
9+
[
10+
mouseup,
11+
[Function],
12+
],
13+
[
14+
touchstart,
15+
[Function],
16+
],
17+
[
18+
touchmove,
19+
[Function],
20+
],
21+
[
22+
touchend,
23+
[Function],
24+
],
25+
]
26+
`;
27+
28+
exports[`utils useMouseAndTouchTracker adds and removes listeners to environment: element change rerender remove events 1`] = `
29+
[
30+
[
31+
mousedown,
32+
[Function],
33+
],
34+
[
35+
mouseup,
36+
[Function],
37+
],
38+
[
39+
touchstart,
40+
[Function],
41+
],
42+
[
43+
touchmove,
44+
[Function],
45+
],
46+
[
47+
touchend,
48+
[Function],
49+
],
50+
]
51+
`;
52+
53+
exports[`utils useMouseAndTouchTracker adds and removes listeners to environment: initial adding events 1`] = `
54+
[
55+
[
56+
mousedown,
57+
[Function],
58+
],
59+
[
60+
mouseup,
61+
[Function],
62+
],
63+
[
64+
touchstart,
65+
[Function],
66+
],
67+
[
68+
touchmove,
69+
[Function],
70+
],
71+
[
72+
touchend,
73+
[Function],
74+
],
75+
]
76+
`;
77+
78+
exports[`utils useMouseAndTouchTracker adds and removes listeners to environment: unmount remove events 1`] = `
79+
[
80+
[
81+
mousedown,
82+
[Function],
83+
],
84+
[
85+
mouseup,
86+
[Function],
87+
],
88+
[
89+
touchstart,
90+
[Function],
91+
],
92+
[
93+
touchmove,
94+
[Function],
95+
],
96+
[
97+
touchend,
98+
[Function],
99+
],
100+
]
101+
`;

src/hooks/__tests__/utils.test.js

+34-44
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('utils', () => {
8484
describe('useMouseAndTouchTracker', () => {
8585
test('renders without error', () => {
8686
expect(() => {
87-
renderHook(() => useMouseAndTouchTracker(undefined, [], jest.fn()))
87+
renderHook(() => useMouseAndTouchTracker(undefined, jest.fn(), []))
8888
}).not.toThrowError()
8989
})
9090

@@ -93,63 +93,53 @@ describe('utils', () => {
9393
addEventListener: jest.fn(),
9494
removeEventListener: jest.fn(),
9595
}
96-
const refs = []
96+
const elements = [{}, {}]
9797
const handleBlur = jest.fn()
98-
99-
const {unmount, rerender, result} = renderHook(() =>
100-
useMouseAndTouchTracker(environment, refs, handleBlur),
98+
const initialProps = {environment, handleBlur, elements}
99+
100+
const {unmount, rerender, result} = renderHook(
101+
props =>
102+
useMouseAndTouchTracker(
103+
props.environment,
104+
props.handleBlur,
105+
props.elements,
106+
),
107+
{initialProps},
101108
)
102109

103110
expect(environment.addEventListener).toHaveBeenCalledTimes(5)
104-
expect(environment.addEventListener).toHaveBeenCalledWith(
105-
'mousedown',
106-
expect.any(Function),
107-
)
108-
expect(environment.addEventListener).toHaveBeenCalledWith(
109-
'mouseup',
110-
expect.any(Function),
111-
)
112-
expect(environment.addEventListener).toHaveBeenCalledWith(
113-
'touchstart',
114-
expect.any(Function),
115-
)
116-
expect(environment.addEventListener).toHaveBeenCalledWith(
117-
'touchmove',
118-
expect.any(Function),
119-
)
120-
expect(environment.addEventListener).toHaveBeenCalledWith(
121-
'touchend',
122-
expect.any(Function),
123-
)
124111
expect(environment.removeEventListener).not.toHaveBeenCalled()
112+
expect(environment.addEventListener.mock.calls).toMatchSnapshot(
113+
'initial adding events',
114+
)
125115

126-
rerender()
116+
environment.addEventListener.mockReset()
117+
environment.removeEventListener.mockReset()
118+
rerender(initialProps)
127119

128120
expect(environment.removeEventListener).not.toHaveBeenCalled()
121+
expect(environment.addEventListener).not.toHaveBeenCalled()
129122

130-
unmount()
123+
rerender({...initialProps, elements: [...elements]})
131124

132125
expect(environment.addEventListener).toHaveBeenCalledTimes(5)
133126
expect(environment.removeEventListener).toHaveBeenCalledTimes(5)
134-
expect(environment.removeEventListener).toHaveBeenCalledWith(
135-
'mousedown',
136-
expect.any(Function),
127+
expect(environment.addEventListener.mock.calls).toMatchSnapshot(
128+
'element change rerender adding events',
137129
)
138-
expect(environment.removeEventListener).toHaveBeenCalledWith(
139-
'mouseup',
140-
expect.any(Function),
130+
expect(environment.removeEventListener.mock.calls).toMatchSnapshot(
131+
'element change rerender remove events',
141132
)
142-
expect(environment.removeEventListener).toHaveBeenCalledWith(
143-
'touchstart',
144-
expect.any(Function),
145-
)
146-
expect(environment.removeEventListener).toHaveBeenCalledWith(
147-
'touchmove',
148-
expect.any(Function),
149-
)
150-
expect(environment.removeEventListener).toHaveBeenCalledWith(
151-
'touchend',
152-
expect.any(Function),
133+
134+
environment.addEventListener.mockReset()
135+
environment.removeEventListener.mockReset()
136+
137+
unmount()
138+
139+
expect(environment.addEventListener).not.toHaveBeenCalled()
140+
expect(environment.removeEventListener).toHaveBeenCalledTimes(5)
141+
expect(environment.removeEventListener.mock.calls).toMatchSnapshot(
142+
'unmount remove events',
153143
)
154144

155145
expect(result.current).toEqual({

src/hooks/useCombobox/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ function useCombobox(userProps = {}) {
9898
})
9999
const mouseAndTouchTrackers = useMouseAndTouchTracker(
100100
environment,
101-
[toggleButtonRef, menuRef, inputRef],
102101
useCallback(
103102
function handleBlur() {
104103
if (latest.current.state.isOpen) {
@@ -110,6 +109,10 @@ function useCombobox(userProps = {}) {
110109
},
111110
[dispatch, latest],
112111
),
112+
useMemo(
113+
() => [menuRef, toggleButtonRef, inputRef],
114+
[menuRef.current, toggleButtonRef.current, inputRef.current],
115+
),
113116
)
114117
const setGetterPropCallInfo = useGetterPropsCalledChecker(
115118
'getInputProps',

src/hooks/useSelect/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function useSelect(userProps = {}) {
4747
const toggleButtonRef = useRef(null)
4848
const menuRef = useRef(null)
4949
const itemRefs = useRef({})
50+
5051
// used to keep the inputValue clearTimeout object between renders.
5152
const clearTimeoutRef = useRef(null)
5253
// prevent id re-generation between renders.
@@ -120,7 +121,6 @@ function useSelect(userProps = {}) {
120121

121122
const mouseAndTouchTrackers = useMouseAndTouchTracker(
122123
environment,
123-
[toggleButtonRef, menuRef],
124124
useCallback(
125125
function handleBlur() {
126126
if (latest.current.state.isOpen) {
@@ -131,6 +131,10 @@ function useSelect(userProps = {}) {
131131
},
132132
[dispatch, latest],
133133
),
134+
useMemo(
135+
() => [menuRef, toggleButtonRef],
136+
[menuRef.current, toggleButtonRef.current],
137+
),
134138
)
135139
const setGetterPropCallInfo = useGetterPropsCalledChecker(
136140
'getMenuProps',

src/hooks/utils.js

+7-8
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
359359
/**
360360
* Tracks mouse and touch events, such as mouseDown, touchMove and touchEnd.
361361
*
362-
* @param {Object} environment The environment to add the event listeners to, for instance window.
363-
* @param {Array<HTMLElement>} downshiftElementRefs The refs for the element that should not trigger a blur action from mouseDown or touchEnd.
364-
* @param {Function} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
365-
* @returns {Object} The mouse and touch events information, if any of are happening.
362+
* @param {Window} environment The environment to add the event listeners to, for instance window.
363+
* @param {() => void} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
364+
* @param {Array<{current: HTMLElement}>} downshiftElementsRefs The refs for the elements that should not trigger a blur action from mouseDown or touchEnd.
365+
* @returns {{isMouseDown: boolean, isTouchMove: boolean, isTouchEnd: boolean}} The mouse and touch events information, if any of are happening.
366366
*/
367367
function useMouseAndTouchTracker(
368368
environment,
369-
downshiftElementRefs,
370369
handleBlur,
370+
downshiftElementsRefs,
371371
) {
372372
const mouseAndTouchTrackersRef = useRef({
373373
isMouseDown: false,
@@ -380,7 +380,7 @@ function useMouseAndTouchTracker(
380380
return noop
381381
}
382382

383-
const downshiftElements = downshiftElementRefs.map(ref => ref.current)
383+
const downshiftElements = downshiftElementsRefs.map(ref => ref.current)
384384

385385
function onMouseDown() {
386386
mouseAndTouchTrackersRef.current.isTouchEnd = false // reset this one.
@@ -431,8 +431,7 @@ function useMouseAndTouchTracker(
431431
environment.removeEventListener('touchmove', onTouchMove)
432432
environment.removeEventListener('touchend', onTouchEnd)
433433
}
434-
// eslint-disable-next-line react-hooks/exhaustive-deps -- refs don't change
435-
}, [environment, handleBlur])
434+
}, [downshiftElementsRefs, environment, handleBlur])
436435

437436
return mouseAndTouchTrackersRef.current
438437
}

0 commit comments

Comments
 (0)