React中动态设置offsets状态时console.log持续输出null的问题
React中动态设置offsets状态时console.log持续输出null的问题
我看了你的代码,发现几个关键问题导致你console.log一直输出null,而且没法在组件挂载时就获取到元素的宽高,咱们一步步来解决:
1. 多余的Ref嵌套导致引用混乱
你同时用了createRef和useRef来包裹引用,这完全是多此一举——gridCol = useRef(gridColRef)这个操作会让你的ref引用层级混乱,直接用useRef(组件生命周期内保持同一引用,比createRef更适合这个场景)就足够了。
把原来的:
let gridColRef = createRef(); let gridCol = useRef(gridColRef);
简化成:
const gridColRef = useRef(null);
之后直接通过gridColRef.current就能访问到DOM元素,不用再套一层current.current。
2. 组件挂载时未主动获取初始宽高
你的代码只有在窗口resize时才会更新offsets状态,但组件刚挂载时并没有主动去获取一次元素的宽高,所以初始的offsets一直是{ offset_width: null, offset_height: null },这就是console.log输出null的核心原因。
3. Resize事件未清理且触发过于频繁
你在useEffect里添加了resize监听,但没有在组件卸载时移除它,可能导致内存泄漏;而且每次窗口resize都会立刻调用setOffsets,频繁触发组件重渲染,性能不够友好,最好加防抖来限制触发频率。
修正后的完整代码
我把所有问题都修复了,还加了详细注释:
import { useEffect, useRef, useState } from "react"; import Section from "./Section"; import QuestionAnswer from "./QuestionAnswer"; export default function FAQ() { const [offsets, setOffsets] = useState({ offset_width: null, offset_height: null }); // 直接用useRef保持组件生命周期内的统一引用 const gridColRef = useRef(null); // 封装复用的宽高更新函数 const updateOffsets = () => { if (gridColRef.current) { const width = gridColRef.current.offsetWidth; const height = gridColRef.current.offsetHeight; setOffsets({ offset_width: width, offset_height: height }); } }; useEffect(() => { // 组件挂载时主动获取一次初始宽高 updateOffsets(); // 给resize事件加防抖,300ms内只执行一次,避免频繁重渲染 const debouncedUpdate = () => { clearTimeout(window.resizeTimeout); window.resizeTimeout = setTimeout(updateOffsets, 300); }; // 添加resize事件监听 window.addEventListener("resize", debouncedUpdate); // 组件卸载时移除监听、清理定时器,防止内存泄漏 return () => { window.removeEventListener("resize", debouncedUpdate); clearTimeout(window.resizeTimeout); }; }, []); // 依赖空数组,只在挂载/卸载时执行 return ( <Section section-name="faq"> <h1 className="faq-header">Frequently asked questions</h1> <div className="grid-container"> <div className="grid-col" ref={gridColRef}> <QuestionAnswer offsets={offsets} question="What is Electrodermal Activity (EDA)?" answers={[ "EDA, often referred to as skin conductance, measures changes in the electrical conductivity of the skin. It's a physiological response linked to emotional arousal and stress.", ]} /> </div> </div> </Section> ); }
额外小提示
JSX属性推荐使用驼峰命名法,比如把<Section section-name="faq">改成<Section sectionName="faq">,这是React的常规写法,避免和HTML自定义属性混淆。
备注:内容来源于stack exchange,提问作者Mig Rivera Cueva
相关产品推荐
相关产品推荐

