Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在事件侦听器函数中无法访问React hooks值_Javascript_Reactjs_Addeventlistener_React Hooks - Fatal编程技术网

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

Javascript 在事件侦听器函数中无法访问React hooks值,javascript,reactjs,addeventlistener,react-hooks,Javascript,Reactjs,Addeventlistener,React Hooks,我决定使用windom width和resize event listener为我的组件使用React挂钩。问题是我无法访问所需的当前值。我得到添加事件侦听器时设置的嵌套值 将函数传递给值设置函数对我来说不是一个解决方案,因为它会强制渲染并破坏我的其他功能 我附上极简主义的例子来说明核心问题: import React, { Component, useState, useEffect } from 'react'; import { render } from 'react-dom'; co

我决定使用windom width和resize event listener为我的组件使用React挂钩。问题是我无法访问所需的当前值。我得到添加事件侦听器时设置的嵌套值

将函数传递给值设置函数对我来说不是一个解决方案,因为它会强制渲染并破坏我的其他功能

我附上极简主义的例子来说明核心问题:

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'));
import React,{Component,useState,useffect}来自'React';
从'react dom'导入{render};
常量应用=()=>{
const[width,setWidth]=useState(0);
常量大小=()=>{
console.log(“width:,width);//即使经过多次更新,也始终为0
setWidth(window.innerWidth);
};
useffect(()=>{
调整大小();
addEventListener(“调整大小”,调整大小);
return()=>window.removeEventListener(“resize”,resize);
}, []);
返回{width};
}
渲染(


请寻求帮助。

每次渲染时,您都会获得一个新的
resize
函数副本。每个副本都捕获
宽度的当前值
。您的侦听器有一个副本,该副本是在第一次渲染时创建的,其宽度为
0

要解决此问题,您有几个选项:

  • width
    更改时更新侦听器

    useEffect(() => {
      resize();
      window.addEventListener("resize", resize);
      return () => window.removeEventListener("resize", resize);
    }, [width]);
    
  • 用于获取侦听器内的当前宽度

    const resize = () => {
      setWidth(oldWidth => {
        console.log("width:", oldWidth);
        return window.innerWidth
      });
    };
    
  • 将宽度存储在


  • 获取数据的另一种方法是设置组件的变量

    import React,{Component,useState,useffect}来自'React';
    从'react dom'导入{render};
    //******* 
    常量appData={
    宽度:0
    }
    //*******
    常量应用=()=>{
    const[width,setWidth]=useState(0);
    常量大小=()=>{
    //*******获得宽度
    console.log('=>',appData.width);
    //*******
    console.log(“width:,width);//即使经过多次更新,也始终为0
    setWidth(window.innerWidth);
    //*******更新宽度
    appData.width=window.innerWidth;
    //*******
    };
    useffect(()=>{
    调整大小();
    addEventListener(“调整大小”,调整大小);
    return()=>window.removeEventListener(“resize”,resize);
    }, []);
    返回{width};
    }
    render(,document.getElementById('root'));
    
    是的。第二个
    useffect
    对这个问题没有帮助。你要么需要在
    width
    更改时删除add listeners,要么用其他方法获取
    width
    的当前值。因此有3种可能的解决方案。第一种是最简单的解决方案。你的代码优化不好,对or没有真正的帮助原始问题。它只是隐藏了问题。第一个
    useffect
    设置一个事件侦听器,将
    width
    重置为初始值。这会触发重新渲染器,第二个
    useffect
    。第二个
    useffect
    width
    设置为正确的值。因此每个调整大小事件都会触发两个重新渲染器,而不是打开e和一个
    resize
    调用使用了错误的值。我喜欢第三种方法。谢谢。
    const widthRef = useRef(width);
    
    const resize = () => {
      console.log("width:", widthRef.current);
      widthRef.current = window.innerWidth;
      setWidth(window.innerWidth);
    };
    
    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'));