Skip to content

Commit

Permalink
Table merge useMergeRefs (#2585)
Browse files Browse the repository at this point in the history
* merge mergeRefs

* changeset

* remove `useMergeRefs` tests from hooks spec file

* deps not depss

* lint
  • Loading branch information
shaneeza authored Dec 11, 2024
1 parent b08696a commit e2cde06
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 80 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-elephants-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/hooks': patch
---

Merges `useMergeRefs` into `useMergeRef` directory
35 changes: 0 additions & 35 deletions packages/hooks/src/hooks.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,41 +94,6 @@ describe('packages/hooks', () => {
});
});

describe('useMergeRefs', () => {
test('should merge refs', () => {
const callbackRefMockFunc = jest.fn();
const callbackRef: React.SetStateAction<HTMLElement | null> = element =>
callbackRefMockFunc(element);
const mutableRef: React.MutableRefObject<HTMLElement | null> = {
current: null,
};

const {
result: { current: mergedCallbackRef },
} = renderHook(() => useMergeRefs([callbackRef, mutableRef]));

expect(mergedCallbackRef).toBeInstanceOf(Function);
expect(callbackRefMockFunc).not.toHaveBeenCalled();
expect(mutableRef.current).toBe(null);

const element = document.createElement('div');
mergedCallbackRef?.(element);

expect(callbackRefMockFunc).toHaveBeenCalledTimes(1);
expect(callbackRefMockFunc).toHaveBeenCalledWith(element);
expect(mutableRef.current).toBe(element);
});

test('should return null when all refs are null or undefined', () => {
const ref1 = null;
const ref2 = undefined;

const { result } = renderHook(() => useMergeRefs([ref1, ref2]));

expect(result.current).toBe(null);
});
});

// Difficult to test a hook that measures changes to the DOM without having access to the DOM
describe.skip('useMutationObserver', () => {}); //eslint-disable-line jest/no-disabled-tests

Expand Down
25 changes: 0 additions & 25 deletions packages/hooks/src/useMergeRefs.ts

This file was deleted.

38 changes: 21 additions & 17 deletions packages/hooks/src/useMergeRefs/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import * as React from 'react';

/**
* Copied from https://github.com/gregberge/react-merge-refs
* @param refs
* @returns
* Merges an array of refs into a single memoized callback ref or `null`.
*/
export function useMergeRefs<Instance>(
refs: Array<React.Ref<Instance> | undefined>,
): React.RefCallback<Instance> | null {
return React.useMemo(() => {
if (refs.every(ref => ref == null)) {
return null;
}

export default function useMergeRefs<T = any>(
refs: Array<
React.MutableRefObject<T> | React.LegacyRef<T> | undefined | null
>,
): React.RefCallback<T> {
return value => {
refs.forEach(ref => {
if (typeof ref === 'function') {
ref(value);
} else if (ref != null) {
(ref as React.MutableRefObject<T | null>).current = value;
}
});
};
return value => {
refs.forEach(ref => {
if (typeof ref === 'function') {
ref(value);
} else if (ref != null) {
(ref as React.MutableRefObject<Instance | null>).current = value;
}
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, refs);
}
40 changes: 37 additions & 3 deletions packages/hooks/src/useMergeRefs/useMergeRefs.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,43 @@
import React from 'react';
import { render } from '@testing-library/react';

import useMergeRefs from '.';
import { renderHook } from '@leafygreen-ui/testing-lib';

test('useMergeRefs', () => {
import { useMergeRefs } from '.';
test('should merge refs', () => {
const callbackRefMockFunc = jest.fn();
const callbackRef: React.SetStateAction<HTMLElement | null> = element =>
callbackRefMockFunc(element);
const mutableRef: React.MutableRefObject<HTMLElement | null> = {
current: null,
};

const {
result: { current: mergedCallbackRef },
} = renderHook(() => useMergeRefs([callbackRef, mutableRef]));

expect(mergedCallbackRef).toBeInstanceOf(Function);
expect(callbackRefMockFunc).not.toHaveBeenCalled();
expect(mutableRef.current).toBe(null);

const element = document.createElement('div');
mergedCallbackRef?.(element);

expect(callbackRefMockFunc).toHaveBeenCalledTimes(1);
expect(callbackRefMockFunc).toHaveBeenCalledWith(element);
expect(mutableRef.current).toBe(element);
});

test('should return null when all refs are null or undefined', () => {
const ref1 = null;
const ref2 = undefined;

const { result } = renderHook(() => useMergeRefs([ref1, ref2]));

expect(result.current).toBe(null);
});

test('returns the correct value for multiple refs', () => {
const TestForwardRefComponent = React.forwardRef(
function TestForwardRefComponent(_, ref) {
React.useImperativeHandle(ref, () => 'refValue');
Expand All @@ -29,7 +63,7 @@ test('useMergeRefs', () => {
expect(refAsObj2.current).toBe('refValue');
});

test('useMergeRefs with undefined and null refs', () => {
test('returns the correct value with undefined and null refs', () => {
const TestForwardRefComponent = React.forwardRef(
function TestForwardRefComponent(_, ref) {
React.useImperativeHandle(ref, () => 'refValue');
Expand Down

0 comments on commit e2cde06

Please sign in to comment.