React hooks value is not accessible in event listener function

Ede*_*ave 4 javascript addeventlistener reactjs react-hooks

I decided to use React hooks for my component using windom width and resize event listener. The problem is that I can't access current value that I need. I get nested value that was set while adding event listener.

Passing function to value setter function is not a solution for me because it's forcing render and breaking my other functionalities.

I am attaching minimalistic example to present core problem:

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

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

  const resize = () => {
    console.log("width:", width); // it's always 0 even after many updates
    setWidth(window.innerWidth);
  };

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

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

render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO IS HERE

Please for help.

Uji*_*T34 10

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]);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用功能更新获取侦听器内部的当前宽度

    const resize = () => {
      setWidth(oldWidth => {
        console.log("width:", oldWidth);
        return window.innerWidth
      });
    };
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将宽度存储在可变引用中

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