如何让useWindowDimensions与useEffect配合触发setDivResize?
问题分析与解决方案
你的代码无法正常工作的核心原因是在useEffect的依赖数组中直接调用useWindowDimensions()违反了React Hooks的调用规则——Hooks必须在组件的顶层作用域调用,不能嵌套在useEffect、循环或条件判断逻辑内。
以下是几种可行的修复方案:
方案一:正确使用自定义窗口尺寸Hook
如果useWindowDimensions是你自己实现的自定义Hook,先在组件顶层调用它,再将返回的尺寸值作为useEffect的依赖:
// 组件顶层调用Hook const { width } = useWindowDimensions(); useEffect(() => { dispatch(setDivResize); }, [width, dispatch]); // 依赖正确的变量,而非Hook调用
确保你的useWindowDimensions实现是正确监听resize事件的:
function useWindowDimensions() { const [dimensions, setDimensions] = useState({ width: window.innerWidth, height: window.innerHeight }); useEffect(() => { const handleResize = () => { setDimensions({ width: window.innerWidth, height: window.innerHeight }); }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return dimensions; }
方案二:直接监听窗口resize事件
如果不需要复用窗口尺寸逻辑,直接在useEffect中添加resize事件监听更简洁,还能避免额外的状态更新开销:
useEffect(() => { const handleResize = () => { dispatch(setDivResize); }; // 添加resize监听 window.addEventListener('resize', handleResize); // 可选:添加防抖处理,避免窗口拖动时频繁触发函数 // const debouncedHandle = debounce(handleResize, 200); // window.addEventListener('resize', debouncedHandle); // 组件卸载时移除监听 return () => window.removeEventListener('resize', handleResize); }, [dispatch]);
方案三:监听div自身的尺寸变化(更精准)
如果你的div尺寸不一定随窗口变化(比如div有固定宽度、父容器限制等),使用ResizeObserver直接监听div的尺寸变化会更精准:
const divRef = useRef(null); useEffect(() => { const observer = new ResizeObserver(() => { if (divRef.current) { // 可获取div实际尺寸,按需传入action const { width, height } = divRef.current.getBoundingClientRect(); dispatch(setDivResize({ width, height })); } }); if (divRef.current) { observer.observe(divRef.current); } return () => observer.disconnect(); }, [dispatch]); // 在JSX中绑定ref到目标div <div ref={divRef}>需要跟踪尺寸的容器</div>
内容的提问来源于stack exchange,提问作者Travis Heeter
相关产品推荐
相关产品推荐

