Add "useDimensions" hook

This commit is contained in:
Justin
2022-06-22 09:25:46 -04:00
parent 8039772d05
commit bdee28fd07
5 changed files with 131 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
import { renderHook, act } from '@testing-library/react-hooks';
import { useDimensions } from '../useDimensions';
let listener: ((rect: any) => void) | undefined = undefined;
(window as any).ResizeObserver = class ResizeObserver {
constructor(ls) {
listener = ls;
}
observe() {}
disconnect() {}
};
describe('useDimensions()', () => {
it('defaults to 0', () => {
const { result } = renderHook(() => useDimensions());
act(() => {
const div = document.createElement('div');
(result.current[0] as any)(div);
});
expect(result.current[1]).toMatchObject({
width: 0,
height: 0,
});
});
it('measures the dimensions of a DOM element', () => {
const { result } = renderHook(() => useDimensions());
act(() => {
const div = document.createElement('div');
(result.current[0] as any)(div);
});
act(() => {
listener!([
{
contentRect: {
width: 200,
height: 200,
},
},
]);
});
expect(result.current[1]).toMatchObject({
width: 200,
height: 200,
});
});
it('disconnects on unmount', () => {
const disconnect = jest.fn();
(window as any).ResizeObserver = class ResizeObserver {
observe() {}
disconnect() {
disconnect();
}
};
const { result, unmount } = renderHook(() => useDimensions());
act(() => {
const div = document.createElement('div');
(result.current[0] as any)(div);
});
expect(disconnect).toHaveBeenCalledTimes(0);
unmount();
expect(disconnect).toHaveBeenCalledTimes(1);
});
});

View File

@@ -1,6 +1,7 @@
export { useAccount } from './useAccount';
export { useAppDispatch } from './useAppDispatch';
export { useAppSelector } from './useAppSelector';
export { useDimensions } from './useDimensions';
export { useFeatures } from './useFeatures';
export { useOnScreen } from './useOnScreen';
export { useOwnAccount } from './useOwnAccount';

View File

@@ -0,0 +1,38 @@
import { Ref, useEffect, useMemo, useState } from 'react';
type UseDimensionsRect = { width: number, height: number };
type UseDimensionsResult = [Ref<HTMLDivElement>, any]
const defaultState: UseDimensionsRect = {
width: 0,
height: 0,
};
const useDimensions = (): UseDimensionsResult => {
const [element, ref] = useState<Element | null>(null);
const [rect, setRect] = useState<UseDimensionsRect>(defaultState);
const observer = useMemo(
() =>
new (window as any).ResizeObserver((entries: any) => {
if (entries[0]) {
const { width, height } = entries[0].contentRect;
setRect({ width, height });
}
}),
[],
);
useEffect((): any => {
if (!element) return null;
observer.observe(element);
return () => {
observer.disconnect();
};
}, [element]);
return [ref, rect];
};
export { useDimensions };