-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Ref was not being passed through for Picker (#2122)
- Pass through ref to SpectrumPicker correctly - Added a `useMultiRef` hook for handling multiple refs being passed in
- Loading branch information
Showing
4 changed files
with
110 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
packages/components/src/spectrum/picker/useMultiRef.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import useMultiRef from './useMultiRef'; | ||
|
||
describe('useMultiRef', () => { | ||
it('should assign the ref to all refs passed in', () => { | ||
const ref1 = jest.fn(); | ||
const ref2 = jest.fn(); | ||
const ref3 = jest.fn(); | ||
const { result } = renderHook(() => useMultiRef(ref1, ref2, ref3)); | ||
const multiRef = result.current; | ||
const element = document.createElement('div'); | ||
multiRef(element); | ||
expect(ref1).toHaveBeenCalledWith(element); | ||
expect(ref2).toHaveBeenCalledWith(element); | ||
expect(ref3).toHaveBeenCalledWith(element); | ||
}); | ||
|
||
it('should assign the ref to all refs passed in with null', () => { | ||
const ref1 = jest.fn(); | ||
const ref2 = jest.fn(); | ||
const ref3 = jest.fn(); | ||
const { result } = renderHook(() => useMultiRef(ref1, ref2, ref3)); | ||
const multiRef = result.current; | ||
multiRef(null); | ||
expect(ref1).toHaveBeenCalledWith(null); | ||
expect(ref2).toHaveBeenCalledWith(null); | ||
expect(ref3).toHaveBeenCalledWith(null); | ||
}); | ||
|
||
it('should work with non-function refs', () => { | ||
const ref1 = { current: null }; | ||
const ref2 = { current: null }; | ||
const ref3 = { current: null }; | ||
const { result } = renderHook(() => | ||
useMultiRef<HTMLDivElement | null>(ref1, ref2, ref3) | ||
); | ||
const multiRef = result.current; | ||
const element = document.createElement('div'); | ||
multiRef(element); | ||
expect(ref1.current).toBe(element); | ||
expect(ref2.current).toBe(element); | ||
expect(ref3.current).toBe(element); | ||
}); | ||
|
||
it('should handle a mix of function and non-function refs', () => { | ||
const ref1 = jest.fn(); | ||
const ref2 = { current: null }; | ||
const ref3 = jest.fn(); | ||
const { result } = renderHook(() => | ||
useMultiRef<HTMLDivElement | null>(ref1, ref2, ref3) | ||
); | ||
const multiRef = result.current; | ||
const element = document.createElement('div'); | ||
multiRef(element); | ||
expect(ref1).toHaveBeenCalledWith(element); | ||
expect(ref2.current).toBe(element); | ||
expect(ref3).toHaveBeenCalledWith(element); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { MutableRefObject, Ref, RefCallback, useCallback } from 'react'; | ||
|
||
/** | ||
* Takes in multiple refs and then returns one ref that can be assigned to the component. | ||
* In turn all the refs passed in will be assigned when the ref returned is assigned. | ||
* @param refs The refs to assign | ||
*/ | ||
function useMultiRef<T>(...refs: readonly Ref<T>[]): RefCallback<T> { | ||
return useCallback(newRef => { | ||
refs.forEach(ref => { | ||
if (typeof ref === 'function') { | ||
ref(newRef); | ||
} else if (ref != null) { | ||
// eslint-disable-next-line no-param-reassign | ||
(ref as MutableRefObject<T | null>).current = newRef; | ||
} | ||
}); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, refs); | ||
} | ||
|
||
export default useMultiRef; |