出于搜索引擎优化和社交媒体链接的原因,我目前正在将ReactJS客户端呈现的应用程序转换为NextJS应用程序。
转换后的组件之一(基本上是等待其完成加载然后逐渐消失的图像)在NextJS环境中使用后无法正常工作。
它的行为如下:
启用缓存:
使用devtools禁用了缓存:
预期的行为以及以前仅使用ReactJS即可实现的行为:
不使用React时,通常是由于有人在定义src
函数之前设置了图像onload
引起的:
let img = new Image()
img.src = "img.jpg"
img.onload = () => console.log("Image loaded.")
应该是:
let img = new Image()
img.onload = () => console.log("Image loaded.")
img.src = "img.jpg"
以下是简化的代码,在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
答案 0 :(得分:5)
由于有人的建议,我最终使用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
答案 1 :(得分:1)
如果您使用的是 nextjs 10 中的新 Image
组件,该组件不支持前向引用,您可以使用
const [loaded, setLoaded] = useState(false)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
if ((ref.current?.firstChild?.firstChild as HTMLImageElement | undefined)?.complete) {
setLoaded(true)
}
}, [])
return <div ref={ref}>
<Image src={src}
onLoad={() => setLoaded(true)}/>
</div>
答案 2 :(得分:1)
从 Next.js v11.0.2-canary.4 开始,可以直接使用 onLoadingComplete
属性。
<Image src={src} onLoadingComplete={() => setLoaded(true)} />
这与其他选项相比如何??
next/image
组件而不是未优化的 img
标签,而无需任何额外的代码或自己处理引用。