custom hook

This commit is contained in:
jerempy
2023-10-04 13:12:52 -04:00
parent b7d569de98
commit 33e5e74228
7 changed files with 102 additions and 67 deletions

View File

@@ -0,0 +1,20 @@
// When testing library added this is unit test for the useMediaQuery
// import { renderHook } from '@testing-library/react-hooks';
// import { useMediaQuery } from '.';
// describe('useMediaQuery', () => {
// it('should update isMobile and isDesktop when window is resized', () => {
// const { result } = renderHook(() => useMediaQuery());
// global.innerWidth = 800;
// global.dispatchEvent(new Event('resize'));
// expect(result.current.isMobile).toBe(true);
// expect(result.current.isDesktop).toBe(false);
// global.innerWidth = 1200;
// global.dispatchEvent(new Event('resize'));
// expect(result.current.isMobile).toBe(false);
// expect(result.current.isDesktop).toBe(true);
// });
// });

View File

@@ -0,0 +1,45 @@
import { useEffect, RefObject, useState } from 'react';
export function useOutsideAlerter<T extends HTMLElement>(
ref: RefObject<T>,
handler: () => void,
additionalDeps: unknown[],
) {
useEffect(() => {
function handleClickOutside(this: Document, event: MouseEvent) {
if (ref.current && !ref.current.contains(event.target as Node)) {
handler();
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, ...additionalDeps]);
}
// Use isMobile for checking if the width is in the expected mobile range (less than 768px)
// use IsDesktop for effects you explicitly only want when width is wider than 960px.
export function useMediaQuery() {
const mobileQuery = '(max-width: 768px)';
const desktopQuery = '(min-width: 960px)';
const [isMobile, setIsMobile] = useState(false);
const [isDesktop, setIsDesktop] = useState(false);
useEffect(() => {
const mobileMedia = window.matchMedia(mobileQuery);
const desktopMedia = window.matchMedia(desktopQuery);
const updateMediaQueries = () => {
setIsMobile(mobileMedia.matches);
setIsDesktop(desktopMedia.matches);
};
updateMediaQueries();
const listener = () => updateMediaQueries();
window.addEventListener('resize', listener);
return () => {
window.removeEventListener('resize', listener);
};
}, [mobileQuery, desktopQuery]);
return { isMobile, isDesktop };
}