Javascript 如何为我的应用程序中需要它的所有React组件提供窗口宽度?
所以我有了这个钩子来返回我的应用程序组件的Javascript 如何为我的应用程序中需要它的所有React组件提供窗口宽度?,javascript,reactjs,responsive-design,react-hooks,Javascript,Reactjs,Responsive Design,React Hooks,所以我有了这个钩子来返回我的应用程序组件的windowWidth。我将此称为选项#1 import {useEffect, useState} from 'react'; function useWindowWidth() { const [windowWidth,setWindowWidth] = useState(window.innerWidth); useEffect(() => { function handleResize() { setWi
windowWidth
。我将此称为选项#1
import {useEffect, useState} from 'react';
function useWindowWidth() {
const [windowWidth,setWindowWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() {
setWindowWidth(window.innerWidth);
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowWidth;
}
export default useWindowWidth;
现在我基本上在每个组件上使用它,这些组件取决于要渲染的窗口宽度,比如:
function Component(props) {
const windowWidth = useWindowWidth();
return(
// RETURN SOMETHING BASED ON WINDOW WIDTH
);
}
而且,由于钩子有一个事件监听器,用于调整大小
事件,因此即使在窗口调整大小之后,组件也会保持响应
但我担心,我正在为每个使用该钩子的组件附加一个新的侦听器,这可能会在某个时候减慢速度。我想到了另一种方法:
选项2
我只在像
这样的顶级组件中使用了useWindowWidth()
钩子一次,我将通过上下文提供整个链的windowWidth
值
比如:
问题
我正在用选项1设置多个
resize
侦听器这一事实困扰我,对吗?选项#2是优化该流的好方法吗?如果您的窗口被您提到的许多组件使用,您必须更喜欢使用上下文。内容如下:
上下文用于全局应用范围
因此,#2
是每个反应器的完美选择
第一种方法#1
可能适用于相同层次结构中的组件,但最多只能达到2-3个级别 我不确定添加和删除事件侦听器是否比设置和删除映射键成本更高,但可能以下操作会对其进行优化:
const changeTracker = (debounceTime => {
const listeners = new Map();
const add = fn => {
listeners.set(fn, fn);
return () => listeners.delete(fn);
};
let debounceTimeout;
window.addEventListener('resize', () => {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(
() => {
const width=window.innerWidth;
listeners.forEach(l => l(width))
},
debounceTime
);
});
return add;
})(200);
function useWindowWidth() {
const [windowWidth, setWindowWidth] = useState(
() => window.innerWidth
);
useEffect(
() =>//changeTracker returns a remove function
changeTracker((width) =>
setWindowWidth(width)
),
[]
);
return windowWidth;
}
自定义钩子使用起来非常好,在卸载组件时删除侦听器。在调整大小时,您可能希望解除锁定,以防止触发许多更新。@HMR谢谢!我有一个脱口而出的版本。但是我多次向窗口
对象添加和删除事件侦听器不是一个问题吗?我不知道,这可能是一个非常便宜的操作,但它有点困扰我,我设置了多个侦听器,而1就足够了。您认为呢?使用上下文或使用诸如redux之类的状态管理器来存储宽度值会有更好的性能,但即使有数百个组件这样做,去抖动也可能是更好的性能提升。您可以将useWindowWidth设置为从单例对象获取其宽度。
function Component() {
const windowWidth = useContext(WindowWidthContext);
return(
// SOMETHING BASED ON WINDOW WIDTH
);
}
const changeTracker = (debounceTime => {
const listeners = new Map();
const add = fn => {
listeners.set(fn, fn);
return () => listeners.delete(fn);
};
let debounceTimeout;
window.addEventListener('resize', () => {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(
() => {
const width=window.innerWidth;
listeners.forEach(l => l(width))
},
debounceTime
);
});
return add;
})(200);
function useWindowWidth() {
const [windowWidth, setWindowWidth] = useState(
() => window.innerWidth
);
useEffect(
() =>//changeTracker returns a remove function
changeTracker((width) =>
setWindowWidth(width)
),
[]
);
return windowWidth;
}