Next.js SSG页面useRef为null致model-viewer AR激活失败问题求助
问题分析
出现这个问题的核心原因有两个:
- 脚本加载与组件渲染顺序不匹配:通过
<Head>引入的model-viewer脚本是异步加载的,而你的useEffect(空依赖数组)会在组件首次挂载时立即执行,此时<model-viewer>可能还未被注册为自定义元素,ref自然拿不到对应的实例。 - Next.js客户端导航特性:使用
next/link跳转属于客户端导航,页面不会完全刷新,<Head>中的脚本可能不会重新加载或初始化,导致首次进入页面时model-viewer元素未完成初始化,ref为null。
解决方案
方案1:等待自定义元素注册完成后执行AR激活
利用浏览器的customElements.whenDefined方法,确保model-viewer自定义元素注册完成后,再获取ref并调用activateAR:
import { useRef, useEffect } from 'react'; import Head from 'next/head'; export default function ARPage() { const viewer = useRef<any>(null); useEffect(() => { async function activateAR() { // 等待model-viewer自定义元素注册完成 await customElements.whenDefined('model-viewer'); if (viewer.current) { viewer.current.activateAR(); } } activateAR(); }, []); return ( <> <Head> <title>argateway</title> <script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js" /> </Head> <model-viewer ref={viewer} ar /> </> ); }
方案2:手动控制脚本加载(更可靠)
如果客户端导航时脚本复用导致的问题依然存在,可以将脚本加载逻辑放到useEffect中,确保每次组件挂载时脚本都已就绪:
import { useRef, useEffect } from 'react'; import Head from 'next/head'; export default function ARPage() { const viewer = useRef<any>(null); useEffect(() => { let scriptLoaded = false; // 检查是否已加载过model-viewer脚本 const existingScript = document.querySelector('script[src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"]'); async function loadScriptAndActivateAR() { if (existingScript) { scriptLoaded = true; } else { const script = document.createElement('script'); script.type = 'module'; script.src = 'https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js'; document.head.appendChild(script); await new Promise(resolve => script.onload = resolve); scriptLoaded = true; } if (scriptLoaded) { await customElements.whenDefined('model-viewer'); try { viewer.current?.activateAR(); } catch (err) { console.error('AR激活失败:', err); // 可在此添加设备不支持AR的降级提示 } } } loadScriptAndActivateAR(); }, []); return ( <> <Head> <title>argateway</title> </Head> <model-viewer ref={viewer} ar /> </> ); }
额外注意事项
- 显式给
<model-viewer>添加ar属性,确保AR功能处于可用状态 - 加入错误捕获逻辑,避免部分不支持WebAR的浏览器/设备导致页面异常
内容的提问来源于stack exchange,提问作者user20942427
相关产品推荐
相关产品推荐

