'Storing width in react context vs hooks

In a production level app is it better to store the screen width in context or use a custom hook to store the device width?

The main code is:

const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);

  const handleWindowResize = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  };

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

Can someone correct me if Im wrong but every time the screen resizes, storing the width in context would re render the entire app for every pixel width changes so there would be a crazy amount of re renders. My thought was to tell my manager that storing it in a hook is better because only the elements using the screen width would be re rendered.



Solution 1:[1]

UPDATED

As for your question,

storing the width in context would re render the entire app for every pixel width changes so there would be a crazy amount of re-renders

I'd say that depends where you consume data

enter image description here Source

Checking the above workflow, you can see only a part of Component 2, which use consume to listen to provider changes, gets re-rendered.

My thought was to tell my manager that storing it in a hook is better because only the elements using the screen width would be re rendered.

Similarly, if you use custom hooks, it will have the same effect as Context API. Where you use hooks, that place will get re-rendered.

In a production level app is it better to store the screen width in context or use a custom hook to store the device width?

window itself is used globally, so I'd suggest using Context API as a better place to keep your window events/states. It can be used effectively in both class-based component and function-based components (hooks only can be used in function-based components)

In the function-based component, you can call useContext hook to get data

const windowProps = useContext(Context)

In class-based component, you can get data via Context.Consumer

<Context.Consumer>
{(windowProps) => <Component {...windowProps} />}
</Context.Consumer>

Lastly, as for your crazy re-rendering concern, you also can use debounce to delay updating states continuously.

OLD ANSWER

You can use debounce to avoid continuous state updates on resize. I'm using setTimeout for the debounce logic

const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
const timer = useRef();

  const handleWindowResize = () => {
    if(timer.current) {
       clearTimeout(timer.current) //if an user try to resize the screen again, we reset timer (no triggering state update logic)
    } 
    timer.current = setTimeout(() => {
       setWidth(window.innerWidth);
       setHeight(window.innerHeight);
    }, 500) //delay state change after 0.5s
  };

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

If you look for a simpler solution, you can use lodash debounce. The logic will be like this

import debounce from 'lodash/debounce'

useEffect(() => {
    window.addEventListener('resize', debounce(handleWindowResize,500));
    return () => window.removeEventListener('resize', debounce(handleWindowResize,500));
  }, []);

If you're not sure what debounce is, you can check this article. This is also very useful for scrolling position updates

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1