React组件:为何在useEffect和回调外打印hiop元素无效?
React组件中hiop元素打印时机问题
组件代码
import { useState, useEffect } from "react" export default function profile() { const [text, setT] = useState("") const f = () => console.log(hiop) const t = "hi boy how r u " function type(s = 100, i = 0, d = 0) { setInterval(() => ( d == 0 ? i++ : i--, i >= t.length && d == 0 ? d = 1 : i == 0 ? d = 0 : 0, setT(t.slice(0, i))), s) } useEffect(() => { type() console.log(hiop) }, []) return ( <h1 id="hiop" onClick={f}>{text}</h1> ) }
问题
为何在useEffect和onClick这类回调函数之外打印hiop元素无法生效,而在这些函数内部执行console.log(hiop)却可以正常运行?
解答
这事儿核心是DOM生成时机和React组件执行流程的差异:
- 组件函数执行时,return里的JSX还只是虚拟DOM,还没转换成真实DOM渲染到页面。此时浏览器还没把id为
hiop的h1元素挂载到全局window对象上,在组件顶层直接打印hiop自然拿不到有效内容。 useEffect的回调会在组件挂载完成后执行——也就是虚拟DOM已经变成真实DOM并插入页面了,这时候浏览器已经自动把id为hiop的元素挂到window上,所以console.log(hiop)能正常拿到元素。- onClick这类事件回调是在用户触发点击时才执行的,此时组件早就渲染完成,真实DOM已经存在,所以也能拿到
hiop元素。
另外提醒:直接用id当作全局变量是浏览器的非标准行为,不推荐依赖这个特性。React里正确获取DOM元素的方式是使用useRef,示例代码如下:
import { useState, useEffect, useRef } from "react" export default function Profile() { const hiopRef = useRef(null) const [text, setT] = useState("") const f = () => console.log(hiopRef.current) const t = "hi boy how r u " function type(s = 100, i = 0, d = 0) { setInterval(() => { if (d === 0) { i++ } else { i-- } if (i >= t.length && d === 0) { d = 1 } else if (i === 0 && d === 1) { d = 0 } setT(t.slice(0, i)) }, s) } useEffect(() => { type() console.log(hiopRef.current) }, []) return ( <h1 ref={hiopRef} onClick={f}>{text}</h1> ) }
内容的提问来源于stack exchange,提问作者AORUS FF
相关产品推荐
相关产品推荐

