NextJS:从缓存加载的图像不会触发 onLoad 事件

Moh*_*lid 6 javascript reactjs next.js

出于搜索引擎优化和社交媒体链接的原因,我目前正在将 ReactJS 客户端呈现的应用程序转换为 NextJS 应用程序。

转换的组件之一,基本上是等待加载完成然后淡入的图像,在 NextJS 环境中使用后无法按预期工作。

它的行为方式如下:

缓存已启用:

  • 第一次加载图像并触发 onLoad 事件从而显示图像。
  • 第二次图像保持隐藏状态,因为从缓存加载图像时不会触发 onLoad 事件。

使用 devtools 禁用缓存:

  • onLoad 事件始终有效,因为图像永远不会从缓存中提供。

预期行为和之前仅使用 ReactJS 实现的行为:

  • onLoad 事件应该触发图像是否从缓存中加载。

当不使用 React 时,这个问题通常是因为有人src在定义onload函数之前设置了图像:

let img = new Image()
img.src = "img.jpg"
img.onload = () => console.log("Image loaded.")
Run Code Online (Sandbox Code Playgroud)

应该是:

let img = new Image()
img.onload = () => console.log("Image loaded.")
img.src = "img.jpg"
Run Code Online (Sandbox Code Playgroud)

这是在 NextJS 中导致相同问题的简化代码:

import React, { useState } from "react"

const Home = () => {
    const [loaded, setLoaded] = useState(false)

    const homeStyles = {
        width: "100%",
        height: "96vh",
        backgroundColor: "black"
    }

    const imgStyles = {
        width: "100%",
        height: "100%",
        objectFit: "cover",
        opacity: loaded ? 1 : 0
    }

    const handleLoad = () => {
        console.log("Loaded")
        setLoaded(true)
    }

    return (
        <div className="Home" style={homeStyles}>
            <img alt=""
                onLoad={handleLoad}
                src="https://images.unsplash.com/photo-1558981001-5864b3250a69?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"
                style={imgStyles}
            />
        </div>
    )
}

export default Home
Run Code Online (Sandbox Code Playgroud)

Moh*_*lid 12

ImageObject.complete由于有人的建议,我最终将其用作解决方法。

我曾经useRef参考图像并检查image.current.complete === true组件是否安装。

这是代码:

import React, { useEffect, useRef, useState } from "react"

const Home = () => {
    const [loaded, setLoaded] = useState(false)

    const image = useRef()

    const homeStyles = {
        width: "100%",
        height: "96vh",
        backgroundColor: "black"
    }

    const imgStyles = {
        width: "100%",
        height: "100%",
        objectFit: "cover",
        opacity: loaded ? 1 : 0
    }

    const handleLoad = () => setLoaded(true)

    useEffect(() => {
        if (image.current.complete) setLoaded(true)
    }, [])

    return (
        <div className="Home" style={homeStyles}>
            <img alt=""
                ref={image}
                onLoad={handleLoad}
                src="https://images.unsplash.com/photo-1558981001-5864b3250a69?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"
                style={imgStyles}
            />
        </div>
    )
}

export default Home
Run Code Online (Sandbox Code Playgroud)

  • 我知道仅出于感激而发表评论是违反规则的,但非常感谢。你真的是一个救星。&lt;3 (5认同)