DEV Community

Cover image for Custom Hook to get window's width and height in React dynamically.
Payalsasmal
Payalsasmal

Posted on

Custom Hook to get window's width and height in React dynamically.

Hey Everyone!, Today we are going to discuss how to get a window's width and height with a custom hook. This coding exercise was asked of me in one of my interviews.
The interviewer asked me, Payal, create one custom hook (for reusing the code) to get the window's width and height dynamically when we resize it.
And I took time to determine that, but today I will make others understand in a 101 way.
So, let's not waste time and start...

I am going to divide it into a few steps. Let's follow these steps:

1. How to get the width and height of a browser window

In JavaScript, we use window.innerWidth and window.innerHeight to get the browser window width and height.
So, we can use the same concept in React too. Because ultimately, React is also a JavaScript library.

2. Let's use "window.innerWidth" and "window.innerHeight" properties.



App.js

import { useRef } from "react";
import "./App.css";

function App() {
  const windowSize = useRef([
    window.innerWidth,
    window.innerHeight,
  ]);
  return (
    <div className="App">
      <div className="window">
        Width : <span>{windowSize.current[0]}</span>
      </div>
      <div className="window">
        Height : <span>{windowSize.current[1]}</span>
      </div>
    </div>
  );
}
export default App;



Enter fullscreen mode Exit fullscreen mode

Image description

Here I used the useRef hook. We know useRef is a mutable object, and it doesn't change its value when a component is updated. Also, changing the value of current property doesn't make it re-render.

So, if we need the window objects to change when we resize the browser object, useRef won't be the right choice.
So, we have to think: if we resize the window using an event listener, that means the state is changing while resizing, What if we use useState to track the state and provide us the value of windows dynamically?
Let's do it in our next step.

3.Add a resize event listener and useState for tracking the state in a custom hook:



useSize.js 

import { useEffect, useState } from "react";
const useSize = () => {
  const [windowSize, setWindowSize] = useState([
    window.innerHeight,
    window.innerWidth,
  ]);

  useEffect(() => {
    const windowSizeHandler = () => {
      setWindowSize([window.innerWidth, window.innerHeight]);
    };
    window.addEventListener("resize", windowSizeHandler);

    return () => {
      window.removeEventListener("resize", windowSizeHandler);
    };
  }, []);

  return windowSize;
};

export default useSize;



Enter fullscreen mode Exit fullscreen mode

Let's break down the code step by step.

  • Let's make a useSize custom hook. In this custom hook, we used the built-in react hook useState, which updates the state variable whenever the window's width and height change.


const [windowSize, setWindowSize] = useState([
    window.innerHeight,
    window.innerWidth,
  ]);


Enter fullscreen mode Exit fullscreen mode

A return value from useState is an array with the values "windowSize" and "setWindowSize." The state is stored in a variable named "windowSize," and anytime the function "setWindowSize" is invoked, it updates the state.

  • useEffect used for the first re-render and when the dependency changes. But there is no dependency array for our case. So it gets called only once. For our case, we are adding a resize hook to the addEventListener() method as an action. As I mentioned, there is no dependency array in useEffect, so the callback function executed only once. That means an event listener is added to the window resize event during the initial rendering of the component, and it remains active throughout the component's lifecycle.


useEffect(() => {
    const windowSizeHandler = () => {
      setWindowSize([window.innerWidth, window.innerHeight]);
    };
    window.addEventListener("resize", windowSizeHandler);



Enter fullscreen mode Exit fullscreen mode
  • removeEventListener() is used to remove the resize event listener in this cleanup function to prevent memory leaks and unnecessary event handling after the component is removed from the DOM


return () => {
      window.removeEventListener("resize", windowSizeHandler);
    };



Enter fullscreen mode Exit fullscreen mode
  • returning the windowSize variable to get the windowSize when we are going to use this useSize custom hook in our different components.


return windowSize;


Enter fullscreen mode Exit fullscreen mode

4.Update the App.js file.
We are importing the useSize custom hook in App.js and utilising it like other hooks.
useSize() is passed to a variable and uses that variable to fetch the width and height from an array. because the windowSize variable is initialised as an array in state.



App.js

import useSize from "./useSize";
import "./App.css";

function App() {
  const windowsize = useSize();

  return (
    <div className="App">
      <div className="window">
        Width : <span>{windowsize[0]}</span>
      </div>
      <div className="window">
        Height : <span>{windowsize[1]}</span>
      </div>
    </div>
  );
}
export default App;


Enter fullscreen mode Exit fullscreen mode

5. Hola, we get the output as we expected.😊
The window's width and height are updated when it's resized.

Image description

Conclusion
By using this hook in a functional component, you can access the current window size as an array and update it automatically whenever the window is resized.

That's All.
It's as easy as eating an ice cream.😋

I hope that was enjoyable.🥳
Happy Coding....👩‍💻

Connect me on

LinkedIn Dev.to blog Dev.to blog Twitter

Image description

Top comments (9)

Collapse
 
dennis_bodine_373daa3eeda profile image
Dennis Bodine

This post was a great starting point for me, I just made a few tweaks to get this running in the newer NextJS flavor of React where the DOM isn't available until inside useEffect():

WindowSize type:

export type WindowSize = {
    width: number;
    height: number;
}
Enter fullscreen mode Exit fullscreen mode

hook:

import { WindowSize } from "@/types/windowSize";
import { useEffect, useState } from "react";
export const useWindowSize = (): WindowSize => {
  const [windowSize, setWindowSize] = useState<WindowSize>({
    width: 0,
    height: 0
});

  useEffect(() => {
    if (windowSize.width == 0) {
        setWindowSize({width: window.outerWidth, height: window.outerHeight});  
    }

    const windowSizeHandler = () => {
      setWindowSize({width: window.outerWidth, height: window.outerHeight});
    };
    window.addEventListener("resize", windowSizeHandler);

    return () => {
      window.removeEventListener("resize", windowSizeHandler);
    };
  }, [windowSize.width]);

  return windowSize;
};
Enter fullscreen mode Exit fullscreen mode

I chose "outerHeight" because that's the number Bootstrap uses for its breakpoints. Works like a champ!!

Collapse
 
payalsasmal profile image
Payalsasmal

Am glad that you liked it ☺️

Collapse
 
artu_hnrq profile image
Arthur Henrique

What a well written post!
Thanks for the sharing, @payalsasmal , it helped my coding

Collapse
 
payalsasmal profile image
Payalsasmal

I am glad that It helped you.

Collapse
 
thekrprince profile image
Kumar Prince

Nice Blog!

Collapse
 
payalsasmal profile image
Payalsasmal

Thank you 🙏

Collapse
 
mustaphav profile image
mustapha

do you have an idea why the initial size when you open up the page is way smaller for me?

Collapse
 
mustaphav profile image
mustapha • Edited

i found the mistake, you switched the order of height and width in your useState and the eventhandler :

const [windowSize, setWindowSize] = useState([
    window.innerHeight,
    window.innerWidth,
  ]);

  useEffect(() => {
    const windowSizeHandler = () => {
      setWindowSize([window.innerWidth, window.innerHeight]);
Enter fullscreen mode Exit fullscreen mode

thats why it used the height as initial width and then when i changed the screen size it used the width again. they need to appear in the same order in both instances

Collapse
 
mustaphav profile image
mustapha

other than that it works great, thank you!