Limboer
Limboer

Reputation: 414

How to observe when window resize stop in React

I want to observer when window stop resizing, cause currently if i listen to the resize event on window, i could only listen to resizing change but not knowing when resizing stops. I checked the event parameter in resizing callback, but did not find and helpful information.

Below is the code i'm trying to complete:

import React, { useState, useEffect } from "react";

export default function App() {
  const [windowResizing, setWindowResizing] = useState(false);

  const handleWindowResize = e => {
    setWindowResizing(true);
  };

  useEffect(() => {
    window.addEventListener("resize", handleWindowResize);

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

  return <div>{JSON.stringify({ windowResizing })}</div>;
}

But this does not work, since windowResizing will keep being true after resizing begins, even i already stops resizing.

So is there any way to observe when window stop resizing and i can then call setState based on that?

Upvotes: 1

Views: 5355

Answers (2)

Benito G&#243;mez
Benito G&#243;mez

Reputation: 35

Small update to Tholle's answer

to include the size and the resizing state

import { useState, useLayoutEffect } from 'react'

// https://stackoverflow.com/a/63010184
function debounce(fn, ms) {
    let timer;
    return _ => {
        clearTimeout(timer);
        timer = setTimeout(_ => {
            timer = null;
            fn.apply(this, arguments);
        }, ms);
    };
}

const useWindowSize = () => {
    const [size, setSize] = useState([0, 0, false]);
    useLayoutEffect(() => {
        let timeout;
        clearTimeout(timeout);
        function updateSize() {
            clearTimeout(timeout);
            setSize([window.innerWidth, window.innerHeight, true]);
            timeout = setTimeout(() => {
                setSize([window.innerWidth, window.innerHeight, false]);
            }, 800);
        }
        const debouncedResizeHandler = debounce(() => updateSize())
        window.addEventListener('resize', debouncedResizeHandler);
        setSize([window.innerWidth, window.innerHeight, false]);
        return () => window.removeEventListener('resize', debouncedResizeHandler);
    }, []);
    return size;
}

export default useWindowSize

Upvotes: 0

Tholle
Tholle

Reputation: 112917

There is no real "resizing state" in the browser; the resize event occurs and then it's over.

You could emulate a resizing state of your own by setting a state variable to true on every resize event, and start a new timeout that will reset it back to false after a small amount of time.

Example

import React, { useState, useEffect } from "react";

export default function App() {
  const [windowResizing, setWindowResizing] = useState(false);

  useEffect(() => {
    let timeout;
    const handleResize = () => {
      clearTimeout(timeout);

      setWindowResizing(true);

      timeout = setTimeout(() => {
        setWindowResizing(false);
      }, 200);
    }
    window.addEventListener("resize", handleResize);

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

  return <div>{JSON.stringify({ windowResizing })}</div>;
}

Upvotes: 3

Related Questions