You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 00:55:12