React Custom Hook: useWindowSize
This challenge asks you to create a custom React hook, useWindowSize, that efficiently tracks the current dimensions of the browser window. This is a fundamental utility for responsive web design, enabling components to adapt their layout or behavior based on the viewport size without manual event listeners in every component.
Problem Description
Your task is to implement a TypeScript React custom hook named useWindowSize. This hook should:
- Track Window Dimensions: It needs to reliably report the current
widthandheightof the browser viewport. - Update on Resize: The hook should automatically update the reported dimensions whenever the browser window is resized.
- Initial State: The hook should provide an initial set of dimensions, ideally based on the window size at the time the hook is first mounted.
- Clean Up: Ensure that any event listeners attached are properly removed when the component using the hook unmounts to prevent memory leaks.
Examples
Example 1:
Consider a component that uses useWindowSize like this:
import React from 'react';
import useWindowSize from './useWindowSize'; // Assuming your hook is in this file
function MyResponsiveComponent() {
const { width, height } = useWindowSize();
return (
<div>
<h1>Window Size</h1>
<p>Width: {width}px</p>
<p>Height: {height}px</p>
</div>
);
}
Input (Initial Load): Assume the browser window is initially 1280px wide and 720px tall.
Output (Rendered in JSX):
<div>
<h1>Window Size</h1>
<p>Width: 1280px</p>
<p>Height: 720px</p>
</div>
Explanation:
The useWindowSize hook is called. It reads the initial window dimensions (1280x720) and returns them. The component then displays these dimensions.
Example 2:
Input (After Resizing): The user resizes the browser window to 800px wide and 600px tall.
Output (Updated Rendered in JSX):
<div>
<h1>Window Size</h1>
<p>Width: 800px</p>
<p>Height: 600px</p>
</div>
Explanation:
The resize event listener within the useWindowSize hook is triggered. It updates its internal state with the new dimensions (800x600). React re-renders MyResponsiveComponent, which now receives and displays the updated width and height.
Example 3: (Edge Case: Server-Side Rendering)
Input: The application is being rendered on the server (e.g., using Next.js with SSR).
Output: The hook should gracefully handle the absence of a window object. It should likely return default or undefined values for width and height initially, and then correctly update them when the component mounts on the client-side and the window object becomes available.
Explanation:
On the server, window is not defined. The hook should not throw an error. It might return an object like { width: undefined, height: undefined } or { width: 0, height: 0 } initially. Once the component mounts in the browser, the useEffect that attaches the event listener will run, and the window object will be available, allowing the hook to get the correct dimensions and start tracking.
Constraints
- The hook must be implemented in TypeScript.
- The hook should return an object with
widthandheightproperties, both of typenumber | undefined. - The hook should avoid unnecessary re-renders. Debouncing or throttling the resize event handler is a good practice, though not strictly mandatory for this basic implementation.
- The hook must not leak memory by forgetting to remove the
resizeevent listener.
Notes
- Consider using
useStateto manage the window dimensions anduseEffectto handle the event listener setup and cleanup. - The
window.innerWidthandwindow.innerHeightproperties are your primary tools here. - Pay close attention to how you handle the initial render and the absence of the
windowobject in non-browser environments (SSR).