1. 问题认知
在 Nextjs 中使用 onLaod 和 useState 来确认 Script 的加载状态时,出现了问题。
例如如下示例。
"use client";
import Script from "next/script";
import { useState } from "react";
export default function Page() {
// 通过 useState 确认脚本是否加载
// 当脚本加载完成时,在 onLoad 中改变 scriptLoad 状态
const [scriptLoad, setScriptLoad] = useState(false);
return (
<div>
<Script
src="https://example.com/sample.js"
onLoad={() => setScriptLoad(true)}
/>
{scriptLoad ? <div>加载完成!</div> : <div>加载中!</div>}
</div>
);
}这样的话,组件第一次挂载并且脚本加载完成后,scriptLoad 状态会从 false 正常变为 true。
问题出在脚本已经加载过一次之后,再次挂载组件的时候。

基本上,Script 组件一旦挂载后,即使用户在 Nextjs 内部的多个路由之间来回跳转,也会保证脚本只加载一次。
因此在访问过该页面之后,再次访问时脚本已处于加载完成状态,于是useState 的状态就不会再发生变化。
2. 使用 onReady 代替 onLoad
无论怎么搜索都找不到解决方法,于是查看了 Script 组件相关的Nextjs 官方文档。
Script 组件一共可以接收 5 个 props。

src:脚本路径
strategy:细粒度控制加载行为。只能在服务器端使用。
onLoad:脚本加载完成后执行
onReady:脚本加载完成并且每次组件挂载时都会执行
onError:脚本加载失败时执行
我之前正是因为用了 onLoad,所以只有在脚本第一次加载时才会发生状态变化。
只要简单地把 onLoad 换成 onReady 就能解决。
...
export default function Page() {
...
<Script
src="https://example.com/sample.js"
onReady={() => setScriptLoad(true)}
/>
...3. 后记
就为了这一个问题,不知道我纠结了多少个小时。
本来想通过 AI 来解决疑问,但不论是 Claude 还是 ChatGPT,都在说 explore 时代的代码,只会胡说八道,真是让人头大。
那一刻特别强烈地觉得,要是身边有个能拉我一把的人就好了。

댓글을 불러오는 중...