score:26

Accepted answer

Every render you get a new copy of resize function. Each copy captures the current value of width. Your listener has a copy which was created on the first render with width = 0.

To fix this issue you have several options:

  1. Update listeners when width changes

    useEffect(() => {
      resize();
      window.addEventListener("resize", resize);
      return () => window.removeEventListener("resize", resize);
    }, [width]);
    
  2. Use functional updates to get the current width inside listener

    const resize = () => {
      setWidth(oldWidth => {
        console.log("width:", oldWidth);
        return window.innerWidth
      });
    };
    
  3. Store the width in a mutable reference

    const widthRef = useRef(width);
    
    const resize = () => {
      console.log("width:", widthRef.current);
      widthRef.current = window.innerWidth;
      setWidth(window.innerWidth);
    };
    

score:-1

Another way to get data is to set variable out of the component

DEMO

import React, { Component, useState, useEffect } from 'react';
import { render } from 'react-dom';

//******* 
const appData = {
      width:0
}
//*******

const App = () => {
  const [width, setWidth] = useState(0);

  const resize = () => {
    //******* get width
    console.log('===>',appData.width);
    //*******

    console.log("width:", width); // it's always 0 even after many updates
    setWidth(window.innerWidth);
    //******* update width
    appData.width = window.innerWidth;
    //*******
  };

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

  return <div>{width}</div>;
}

render(<App />, document.getElementById('root'));

Related Query

More Query from same tag