1

I'm using the following hook (taken from Get viewport/window height in ReactJS). I've adapted the hook so it can be rendered on the server (by gating access to window inside a conditional).

import { useState, useEffect } from 'react';

function getWindowDimensions() {
  if (typeof window !== 'undefined') {
    const { innerWidth: width, innerHeight: height } = window;
    return {
      width,
      height
    };
  }
  return { width: -1, height: -1 }
}

export default function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }

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

  return windowDimensions;
}

I've noticed something interesting / confusing:

  1. The hook does return the default values of {width: -1, height: -1} when it is rendered on the server
  2. These values are seemingly observed by parent component. Example:
export default function FooComponent() {
    const { width, height} = useWindowDimensions();
    // this invariant fails
    invariant(width > -1 && height > -1);

}

However, if I insert a console.log(width, height), below the invariant(...) line, I never see -1, -1 in the browser console.

So it looks like the invariant is only triggered on the server and console.log is only run on the client. Can someone explain what's going on here? I.e, why does the component not observe default server side values?

Foobar
  • 7,458
  • 16
  • 81
  • 161

1 Answers1

0

Is it invariant from https://github.com/zertosh/invariant ?

A note on the readme says that if process.env.NODE_ENV is not production it'll throw even if condition is true.

And for component that should only render client side, there is a cool package by SergioDXA (a top remix contributor) : https://github.com/sergiodxa/remix-utils#clientonly

rphlmr
  • 838
  • 6
  • 12