我决定通过windom宽度和resize事件监听器将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'));
请寻求帮助。
答案 0 :(得分:5)
每个渲染都会得到resize
函数的新副本。每个副本都捕获width
的当前值。您的听众有一个副本,该副本是使用width = 0
在第一个渲染上创建的。
要解决此问题,您有几种选择:
width
更改时更新侦听器
useEffect(() => {
resize();
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
}, [width]);
使用functional updates获取监听器中的当前宽度
const resize = () => {
setWidth(oldWidth => {
console.log("width:", oldWidth);
return window.innerWidth
});
};
将宽度存储在mutable reference
中const widthRef = useRef(width);
const resize = () => {
console.log("width:", widthRef.current);
widthRef.current = window.innerWidth;
setWidth(window.innerWidth);
};
答案 1 :(得分:0)
获取数据的另一种方法是在组件之外设置变量
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'));