Design Converter
Education
Last updated on Jan 31, 2025
•8 mins read
Last updated on Jan 31, 2025
•8 mins read
In the ever-evolving landscape of web development, creating responsive React applications that adapt seamlessly to various screen sizes is paramount. Understanding and managing the browser window width and other dimensions ensures that your app delivers an optimal user experience across devices.
This blog delves into crafting a custom useWindowSize
hook, enabling React components to access and respond to window size changes effectively.
Responsive design is a cornerstone of modern web development, ensuring that applications look and function well on a variety of devices and screen sizes. In the context of React, achieving responsive design involves dynamically adjusting the layout and elements based on the dimensions of the browser window. This is where the custom useWindowSize
hook comes into play. By leveraging this hook, developers can easily access the current width and height of the browser window, allowing for real-time adjustments that enhance the user experience. The useWindowSize
hook simplifies the process of creating responsive React apps, making it a valuable tool in any developer’s toolkit.
Every React app interacts with the window
object to determine the current width and height of the browser window. By accessing the window dimensions, developers can tailor components to render appropriately based on the screen size. Whether you're designing for desktop or mobile applications, accurately tracking the window's width and height is crucial for responsive design.
useWindowSize
HookTo streamline the process of tracking window size, we'll create a custom hook named useWindowSize
. This hook leverages the power of useState
and useEffect
hooks to monitor and update the window dimensions dynamically.
1// useWindowSize.js 2import { useState, useEffect } from 'react'; 3 4const useWindowSize = () => { 5 const [windowSize, setWindowSize] = useState({ 6 width: window.innerWidth, 7 height: window.innerHeight, 8 }); 9 10 const handleResize = () => { 11 setWindowSize({ 12 width: window.innerWidth, 13 height: window.innerHeight, 14 }); 15 }; 16 17 useEffect(() => { 18 window.addEventListener('resize', handleResize); 19 return () => window.removeEventListener('resize', handleResize); 20 }, []); 21 22 return windowSize; 23}; 24 25export default useWindowSize;
The useWindowSize
hook operates by utilizing two fundamental React hooks: useState
and useEffect
. Initially, useState
is employed to store the current window dimensions within the component’s state. This state is then dynamically updated through the useEffect
hook, which sets up an event listener for the window’s resize event. Whenever the window is resized, the event listener triggers the handleResize
function, updating the state with the new window dimensions. The hook ultimately returns an object containing the current width and height of the window. This object can be used within React components to adjust layouts and elements, ensuring that the app remains responsive to changes in window size.
useState
and useEffect
HooksThe useState
hook initializes the windowSize
state with the current width and height of the browser window. Meanwhile, the useEffect
hook sets up an event listener for the resize
event, ensuring that any change in window size updates the state accordingly. This combination allows React components to access real-time window dimensions effortlessly.
Handling window resizing involves adding an event listener for the resize
event. This listener invokes the handleResize
function, updating the windowSize
state with the new dimensions. By monitoring the window's width and height, components can adjust their layout dynamically to maintain responsiveness.
It's essential to include a cleanup function within the useEffect
hook to remove the event listener when the component unmounts. This practice prevents potential memory leaks by ensuring that the application doesn't retain unnecessary references to the window
object after the component is no longer in use.
useWindowSize
Hook in ComponentsIntegrating the useWindowSize
hook into your React components is straightforward. By importing and invoking the hook, components gain access to the current window size, enabling conditional rendering based on screen dimensions.
1// ExampleComponent.js 2import React from 'react'; 3import useWindowSize from './useWindowSize'; 4 5const ExampleComponent = () => { 6 const { width, height } = useWindowSize(); 7 8 return ( 9 <div> 10 <h1>Current Window Size</h1> 11 <p>Width: {width}px</p> 12 <p>Height: {height}px</p> 13 {width > 768 ? <DesktopView /> : <MobileView />} 14 </div> 15 ); 16}; 17 18export default ExampleComponent;
Mobile applications often experience frequent changes in screen size due to device rotation or multitasking. The useWindowSize
hook ensures that your React app remains responsive by updating components in real-time as the browser window dimensions fluctuate, providing a seamless user experience across all devices.
useCallback
To enhance performance, especially in complex applications, integrating the useCallback
hook can optimize the handleResize
function. This prevents unnecessary re-creations of the function on every render, ensuring that event listeners remain efficient and do not degrade application performance.
1// useWindowSize.js 2import { useState, useEffect, useCallback } from 'react'; 3 4const useWindowSize = () => { 5 const [windowSize, setWindowSize] = useState({ 6 width: window.innerWidth, 7 height: window.innerHeight, 8 }); 9 10 const handleResize = useCallback(() => { 11 setWindowSize({ 12 width: window.innerWidth, 13 height: window.innerHeight, 14 }); 15 }, []); 16 17 useEffect(() => { 18 window.addEventListener('resize', handleResize); 19 return () => window.removeEventListener('resize', handleResize); 20 }, [handleResize]); 21 22 return windowSize; 23}; 24 25export default useWindowSize;
Understanding the flow of the useWindowSize
hook can be simplified with a Mermaid diagram. This visualization illustrates how the hook interacts with the window object, manages state, and updates components upon window resizing.
useWindowSize
HookTesting the useWindowSize
hook involves simulating window resize events and verifying that the hook accurately updates the window dimensions. Tools like Jest and React Testing Library can facilitate comprehensive testing, ensuring that components respond correctly to changes in window size.
1// useWindowSize.test.js 2import { renderHook, act } from '@testing-library/react-hooks'; 3import useWindowSize from './useWindowSize'; 4 5test('should return initial window size', () => { 6 const { result } = renderHook(() => useWindowSize()); 7 expect(result.current.width).toBe(window.innerWidth); 8 expect(result.current.height).toBe(window.innerHeight); 9}); 10 11test('should update window size on resize', () => { 12 const { result } = renderHook(() => useWindowSize()); 13 14 act(() => { 15 window.innerWidth = 500; 16 window.innerHeight = 500; 17 window.dispatchEvent(new Event('resize')); 18 }); 19 20 expect(result.current.width).toBe(500); 21 expect(result.current.height).toBe(500); 22});
To further optimize performance, especially during rapid resize events, implementing throttling or debouncing techniques can limit the frequency of state updates. This ensures that the application remains responsive without overwhelming the browser with excessive event listeners.
1// useWindowSize.js with debounce 2import { useState, useEffect, useCallback } from 'react'; 3import debounce from 'lodash.debounce'; 4 5const useWindowSize = () => { 6 const [windowSize, setWindowSize] = useState({ 7 width: window.innerWidth, 8 height: window.innerHeight, 9 }); 10 11 const handleResize = useCallback( 12 debounce(() => { 13 setWindowSize({ 14 width: window.innerWidth, 15 height: window.innerHeight, 16 }); 17 }, 100), 18 [] 19 ); 20 21 useEffect(() => { 22 window.addEventListener('resize', handleResize); 23 return () => { 24 handleResize.cancel(); 25 window.removeEventListener('resize', handleResize); 26 }; 27 }, [handleResize]); 28 29 return windowSize; 30}; 31 32export default useWindowSize;
useWindowSize
HookThe useWindowSize
hook can be extended to include additional functionalities, such as tracking other window properties or integrating with other custom hooks. This flexibility allows developers to tailor the hook to specific application requirements, enhancing its utility across various components.
1// useEnhancedWindowSize.js 2import { useState, useEffect, useCallback } from 'react'; 3import debounce from 'lodash.debounce'; 4 5const useEnhancedWindowSize = () => { 6 const [windowSize, setWindowSize] = useState({ 7 width: window.innerWidth, 8 height: window.innerHeight, 9 scrollY: window.scrollY, 10 }); 11 12 const handleResize = useCallback( 13 debounce(() => { 14 setWindowSize({ 15 width: window.innerWidth, 16 height: window.innerHeight, 17 scrollY: window.scrollY, 18 }); 19 }, 100), 20 [] 21 ); 22 23 const handleScroll = useCallback( 24 debounce(() => { 25 setWindowSize((prev) => ({ 26 ...prev, 27 scrollY: window.scrollY, 28 })); 29 }, 100), 30 [] 31 ); 32 33 useEffect(() => { 34 window.addEventListener('resize', handleResize); 35 window.addEventListener('scroll', handleScroll); 36 return () => { 37 handleResize.cancel(); 38 handleScroll.cancel(); 39 window.removeEventListener('resize', handleResize); 40 window.removeEventListener('scroll', handleScroll); 41 }; 42 }, [handleResize, handleScroll]); 43 44 return windowSize; 45}; 46 47export default useEnhancedWindowSize;
Creating responsive React apps requires adherence to best practices that ensure a seamless user experience across various devices and screen sizes. Here are some key practices to consider:
Leverage the useWindowSize
Hook: Use the useWindowSize
hook to access the current window dimensions and adjust your layout and elements accordingly.
Utilize Media Queries: Define different styles for different screen sizes and devices using CSS media queries.
Employ Flexible Units: Use flexible units such as percentages and ems for defining element sizes and margins, rather than fixed units like pixels.
Avoid Fixed Units: Fixed units can lead to layouts that do not adapt well to different screen sizes, so it’s best to avoid them.
Test Across Devices: Regularly test your React app on various devices and screen sizes to ensure a consistent and seamless user experience.
By following these best practices and incorporating the useWindowSize
hook, you can develop responsive React apps that adapt fluidly to different screen sizes and devices, ultimately providing a superior user experience.
Crafting a responsive React application requires meticulous management of window dimensions and screen sizes. By creating a custom useWindowSize
hook, developers can efficiently track and respond to window resizing events, ensuring that components render optimally across all devices. This approach not only simplifies state management but also enhances the overall performance and user experience of React apps.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.