React中useEffect无法获取动态生成DOM元素但可获取静态DOM元素的问题咨询
嘿,这个问题其实是React渲染时机和useEffect依赖项的问题,我来给你拆解清楚:
问题根源
你用的是空依赖数组的useEffect(() => {}, []),它只会在组件首次挂载完成后执行一次。但核心问题在于:当组件首次挂载时,你的games数组大概率还是空的!
看你的createSlides函数:如果games.length === 0就直接返回undefined,这时候组件渲染时根本不会生成那些.gaming__feature-img-container元素。而.gaming__feature-section是硬编码的静态元素,组件挂载时它必然已经存在于DOM中,所以你能正常获取到它。
等后续games数据加载完成(比如从接口请求回来),createSlides才会生成对应的JSX,组件重新渲染后这些slide元素才会出现在DOM里,但这时候空依赖的useEffect已经执行过了,不会再触发,所以你控制台打印的slides还是空列表。
解决方案
这里有两种常用的处理方式,都能完美解决你的问题:
1. 给useEffect添加正确的依赖项
把games加入useEffect的依赖数组,这样每当games更新(从空数组变为有数据的数组),useEffect就会重新执行,此时动态生成的slide元素已经渲染到DOM里了,就能正常获取到:
useEffect(() => { const slides = document.querySelectorAll(".gaming__feature-img-container"); const el2 = document.querySelector(".gaming__feature-section"); console.log(slides); console.log(el2); }, [games]); // 这里添加games作为依赖项
2. 使用React的Ref(更符合React最佳实践)
直接操作DOM虽然能解决问题,但React更推荐用ref来引用元素,尤其是动态生成的列表。你可以用useRef创建一个容器,把每个slide的ref存进去:
import { useRef, useEffect } from 'react'; function YourComponent() { const slideRefs = useRef([]); const games = // 你的games数据,比如从useState或props获取 const createSlides = () => { if (games.length === 0) return []; return games.map((game, i) => ( <figure key={game.id} data-gameid={game.id} className="gaming__feature-img-container" ref={el => slideRefs.current[i] = el} // 给每个slide绑定ref > <img alt="game" src={game.imgUrl} className="gaming__feature-slider-img" /> </figure> )); }; const slides = createSlides(); useEffect(() => { // 当games有数据时,slideRefs.current里就有对应的DOM元素了 console.log(slideRefs.current); const el2 = document.querySelector(".gaming__feature-section"); console.log(el2); }, [games]); return ( <div className="gaming__feature-section"> {slides} </div> ); }
这种方式不需要用querySelectorAll去查找DOM,而是通过React的ref直接获取元素,更可靠也更贴合React的设计理念~
备注:内容来源于stack exchange,提问作者Bobi

