简体   繁体   English

事件侦听器函数中无法访问React hooks值

[英]React hooks value is not accessible in event listener function

I decided to use React hooks for my component using windom width and resize event listener. 我决定使用Windom width和resize事件监听器为我的组件使用React钩子。 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. 将函数传递给值setter函数对我来说不是一个解决方案,因为它强制渲染并破坏我的其他功能。

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'));

LIVE DEMO IS HERE 现场演示就在这里

Please for help. 请帮忙。

Every render you get a new copy of resize function. 每个渲染都会获得一个resize函数的新副本。 Each copy captures the current value of width . 每个副本捕获width的当前值。 Your listener has a copy which was created on the first render with width = 0 . 您的侦听器具有在第一个渲染时创建的副本,其width = 0

To fix this issue you have several options: 要解决此问题,您有以下几种选择:

  1. Update listeners when width changes width更改时更新侦听器

     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); }; 

Another way to get data is to set variable out of the component 获取数据的另一种方法是将变量设置在组件之外

DEMO 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'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM