Explain Codes LogoExplain Codes Logo

Get viewport/window height in ReactJS

javascript
responsive-design
custom-hooks
event-listener
Anton ShumikhinbyAnton Shumikhin·Aug 13, 2024
TLDR

Here's the speed-run version for obtaining viewport height in React by using window.innerHeight inside a custom hook for real-time updates:

import React, { useState, useEffect } from 'react'; function useViewportHeight() { // Well, it's high time we knew our height const [height, setHeight] = useState(window.innerHeight); useEffect(() => { // Let's react to some resizing action here. const updateHeight = () => setHeight(window.innerHeight); window.addEventListener('resize', updateHeight); // On second thought, let's ghost this 'resize' event once we're done. return () => window.removeEventListener('resize', updateHeight); }, []); return height; } function ViewportHeightComponent() { const height = useViewportHeight(); // Who said height was just a number? return <div>Viewport height: {height}px</div>; }

This code will create a hook, named useViewportHeight, that keeps an eye on the viewport height—even when resizing!

How to dodge the SSR bullet

Server-side rendering in React doesn't provide window—you're in command-line territory. Thus, to prevent a catastrophic failure, always verify window's existence:

function useViewportHeight() { // A height of 0 can always be measured! const [height, setHeight] = useState(0); useEffect(() => { if (typeof window !== 'undefined') { // Phew! We have a window, let's get its height. setHeight(window.innerHeight); const updateHeight = () => setHeight(window.innerHeight); window.addEventListener('resize', updateHeight); // Goodbye, 'resize' event. It was nice meeting you. return () => window.removeEventListener('resize', updateHeight); } }, []); return height; }

Class Component lifecycle: It's a circle of life

In the realm of Class Components, handling window height has its lifecycle:

import React from 'react'; class ViewportHeightComponent extends React.Component { // Our height is never out of style. state = { height: window.innerHeight }; // Some call it growing up, I call it resizing! updateDimensions = () => { this.setState({ height: window.innerHeight }); }; componentDidMount() { // The more the merrier! Joining the 'resize' party. window.addEventListener('resize', this.updateDimensions); } componentWillUnmount() { // Time to say goodbye to 'resize'. You will be missed. window.removeEventListener('resize', this.updateDimensions); } render() { // Sharing height just like office gossip. return <div>Viewport height: {this.state.height}px</div>; } }

Binding updateDimensions in the constructor or using arrow functions guarantees the correct reference of this.

Making it snappier, Reusability and Best Practices

Custom Hooks: Your magic spell

Custom hooks like useViewportHeight offer convenient quick fixes and less clutter, making more readable components. Plus, you get to share logic all around town without cramming everything into higher-order components or render props.

Prevent Memory Leaks: Fight the good fight

In useEffect, cleaning up after yourself is top-tier etiquette. Unwanted event listeners could lead to performance issues and memory leaks. So, before stepping out, make sure you've got everything (listeners removed).

Event Listener: Getting the name right

Always carefully jot down the correct event name (resize) and a consistent event handler function before adding or removing listeners. Inconsistent references could leave you with unnecessary hang-ups (listeners).

Lifecycle Methods: Avoid the deprecated

When selecting React lifecycle methods, discard componentWillMount; it's no longer invited to the party. Instead, invite componentDidMount to initialize event listeners or state.

Stick the Landing with Responsive Design

Viewport height might play a vital role in styling or conditional rendering. React's proptypes and defaultProps offer default initial values and type assertions, making your components more predictable and less prone to errors.