所以我有这个钩子来返回我的应用程序组件的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
);
}
由于钩子有一个用于resize
事件的事件侦听器,因此即使在窗口调整大小后,组件也会保持响应。
但我担心我会为每个使用该钩子的组件附加一个新的监听器,这可能会在某个时候减慢速度。我想到了另一种方法:
选项#2
我只使用过一次useWindowWidth()
挂钩,在像<App/>
这样的顶级组件中,我将通过上下文提供链下的windowWidth
值。
类似:
function App() {
const windowWidth = useWindowWidth();
return(
<WindowWidthContext.Provider value={windowWidth}>
<Rest_of_the_app/>
</WindowWidthContext.Provider>
);
}
然后,每个需要它的组件都可以通过获得它
function Component() {
const windowWidth = useContext(WindowWidthContext);
return(
// SOMETHING BASED ON WINDOW WIDTH
);
}
问题
我正在用选项#1设置多个resize
侦听器,这让我感到困扰,这是对的吗?选项#2是优化该流的好方法吗?
如果您的窗口被您提到的这么多组件使用,那么您一定更喜欢使用context
。如下所示:
Context用于全局应用范围。
因此,#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在上面的一个线程中所说,我的解决方案是使用redux来保持宽度值。使用此策略,您只需要一个监听器,并且可以限制使用任何您喜欢的工具更新的频率。您可以检查宽度值是否在新断点的范围内,并且只有在为true时才更新redux。只有当您的组件不需要稳定的窗口宽度时,这才有效,在这种情况下,只需要去抖动。