--- tags: - javascript - react --- # Custom hook examples ## Determine viewport width ### Hook ```js // useViewportWidth.js import { useEffect, useState } from "react"; export default function (viewportWidth) { const [matchesViewportWidth, setMatchesViewportWidth] = useState(false); useEffect(() => { const handleResize = () => window.innerWidth < viewportWidth ? setMatchesViewportWidth(true) : setMatchesViewportWidth(false); window.addEventListener("resize", handleResize); // Call on initialization to determine initial width handleResize(); // Clean-up listener to prevent memory leaks return () => window.removeEventListener("resize", handleResize); }, [viewportWidth]); return matchesViewportWidth; } ``` ### Unit test ```js import useViewportWidth from "./useViewportWidth"; import { fireEvent } from "@testing-library/react"; import { act } from "react-dom/test-utils"; import { renderHook } from "@testing-library/react-hooks"; describe("useViewportWidth", () => { it("returns `true` when window resized to mobile viewport width", () => { // Arrange const { result } = renderHook(() => useViewportWidth(768)); // Act act(() => { window.innerWidth = 500; fireEvent(window, new Event("resize")); }); // Assert expect(result.current).toBe(true); }); it("returns `false` when window resized to width greater than mobile viewport", () => { // Arrange const { result } = renderHook(() => useViewportWidth(768)); // Act act(() => { window.innerWidth = 1058; fireEvent(window, new Event("resize")); }); // Assert expect(result.current).toBe(false); }); })``; ```