如果我不滚动或单击浏览器,组件内部的 React useState() 数组映射不会更新

React useState() array mapping inside of component doesn't update if I don't scroll or click on browser

我用 React 和 Tailwind 制作了这个效果:

GIF with the effect

如您所见,到目前为止一切顺利。但是,此效果仅在以下情况下有效:

当我不执行上述操作时会发生这种情况:

GIF with the effect but not working as expected

如您所见,这不是我想要的效果。

所以,显然,这里出现了 React 渲染问题,我被困住了。

在内部,其工作方式如下:

const HomeHeader = () => {

    // This are imported images
    const IMAGES = [insta, twitter, netflix, mix];

    // This is an array that maps inside the component and renders the images as JSX
    const [images, setImages] = useState([]);

    useEffect(() => {
        let counter = 0;
        
        // An interval that creates a new element in the array "images" every 50 miliseconds
        const interval = setInterval(() => {
            setImages(prevState => [
                ...prevState,
                {
                    id: counter++,
                    duration: getRandom(5, 9) * 1000,
                    image: IMAGES[getRandom(0, IMAGES.length)],
                    height: getRandom(1, 6),
                    top: getRandom(0, window.innerHeight - window.innerHeight / 4),
                    right: getRandom(0, window.innerWidth)
                }
            ]);
        }, 50);
        return () => clearInterval(interval);
    }, [])

    // Every time the state variable "images" is changed, add the cool animation to the last image and, when it ends, delete the image from the HTML
    useEffect(() => {
        if(images.length > 0) {
            let image = images[images.length - 1];
            let element = document.getElementById(image.id);
            element.classList.add('opacity-0');
            element.classList.add('scale-125');
            
            setTimeout(() => {
                element.parentNode.removeChild(element);
            }, image.duration);
        }
    }, [images])

    return (
        <div id="header" className="relative h-full bg-gray-900 flex justify-center items-center px-16 overflow-hidden">
        <h1 className="bg-black text-gray-200 font-bold text-5xl sm:text-8xl md:text-9xl text-center z-10"></h1>
        {
            images.map((element, index) => {
                return <img key={index} id={element.id} src={element.image} style={{top: element.top, right: element.right}} className={"imageRRSS absolute filter blur-sm w-auto h-" + element.height + "/6 w-auto transform transition-transform-opacity duration-" + element.duration}/>
            })
        }
    </div>
    )
}

它的作用是每 50 毫秒向状态数组 images 添加一个新对象,其中包含要添加的图像的属性。

每次添加后,由于是状态变量,React会重新渲染组件内部的映射 return:

        {
            images.map((element, index) => {
                return <img key={index} id={element.id} src={element.image} style={{top: element.top, right: element.right}} className={"imageRRSS absolute filter blur-sm w-auto h-" + element.height + "/6 w-auto transform transition-transform-opacity duration-" + element.duration}/>
            })
        }

它还会转到 useEffect 并添加很酷的动画,当动画结束时,它会从 HTML:

中删除标签
useEffect(() => {
        if(images.length > 0) {
            let image = images[images.length - 1];
            let element = document.getElementById(image.id);
            element.classList.add('opacity-0');
            element.classList.add('scale-125');
            
            setTimeout(() => {
                element.parentNode.removeChild(element);
            }, image.duration);
        }
    }, [images])

但是,渲染只是在我与浏览器交互时发生。

这就是我对发生的事情的理解。但是,显然有些地方不对劲,因为它没有按预期工作。

有人知道这是怎么回事吗?

谢谢!

好的,解决了。问题在于 React 在元素中立即应用顺风效果。我只是将 onLoad 事件添加到组件中,而不是使用 useEffect,它工作得很好。