咨询:Next.js/Script加载CMS动态365表单,页面返回后无法渲染的解决办法
解决Next.js导航返回后动态365表单不渲染的问题
方案1:结合路由监听重新触发表单初始化
Next.js客户端导航时,Script组件不会自动重新执行缓存的脚本,可通过监听路由变化,在回到目标页面时手动触发表单初始化逻辑:
import { useRouter } from 'next/router'; import Script from 'next/script'; import { useEffect, useState } from 'react'; export default function FormPage() { const router = useRouter(); const [shouldInitForm, setShouldInitForm] = useState(true); const init365Form = () => { // 替换为365表单的实际初始化函数,比如调用其全局初始化方法 if (window.initMicrosoftForm) { window.initMicrosoftForm('#form-container'); } }; useEffect(() => { const handleRouteChange = (url) => { // 根据实际路由调整判断条件 if (url === '/form-page') { setShouldInitForm(true); } }; router.events.on('routeChangeComplete', handleRouteChange); return () => { router.events.off('routeChangeComplete', handleRouteChange); }; }, [router]); useEffect(() => { if (shouldInitForm) { init365Form(); setShouldInitForm(false); } }, [shouldInitForm]); return ( <> <div id="form-container"></div> <Script src="https://your-cms-form-script-url.js" strategy="afterInteractive" onLoad={init365Form} /> </> ); }
方案2:手动注入/移除脚本避免缓存
绕过Next.js Script组件的缓存机制,在组件挂载时手动创建脚本标签,卸载时移除,确保每次进入页面都重新加载脚本:
import { useEffect } from 'react'; export default function FormPage() { const init365Form = () => { if (window.initMicrosoftForm) { window.initMicrosoftForm('#form-container'); } }; useEffect(() => { const script = document.createElement('script'); script.src = 'https://your-cms-form-script-url.js'; script.async = true; script.onload = init365Form; document.body.appendChild(script); return () => { // 卸载时清理脚本和全局变量 document.body.removeChild(script); delete window.initMicrosoftForm; }; }, []); return <div id="form-container"></div>; }
方案3:通过key强制重置表单容器
给表单容器添加基于路由状态的key,让React在页面返回时重新渲染容器,确保脚本执行时能找到全新的DOM节点:
import { useRouter } from 'next/router'; import Script from 'next/script'; import { useEffect } from 'react'; export default function FormPage() { const router = useRouter(); // 用asPath作为key,路由变化后容器自动重新渲染 const containerKey = router.asPath; const init365Form = () => { if (window.initMicrosoftForm) { window.initMicrosoftForm('#form-container'); } }; useEffect(() => { // 延迟执行确保DOM已就绪 const timer = setTimeout(init365Form, 100); return () => clearTimeout(timer); }, [containerKey]); return ( <> <div id="form-container" key={containerKey}></div> <Script src="https://your-cms-form-script-url.js" strategy="lazyOnload" /> </> ); }
方案4:App Router下的客户端组件处理(Next.js 13+)
如果使用App Router,将表单组件标记为客户端组件,结合路由监听处理:
'use client'; import { usePathname } from 'next/navigation'; import Script from 'next/script'; import { useEffect, useState } from 'react'; export default function FormPage() { const pathname = usePathname(); const [shouldInit, setShouldInit] = useState(true); const initForm = () => { if (window.initMicrosoftForm) { window.initMicrosoftForm('#form-container'); } }; useEffect(() => { if (pathname === '/form-page') { setShouldInit(true); } }, [pathname]); useEffect(() => { if (shouldInit) { initForm(); setShouldInit(false); } }, [shouldInit]); return ( <> <div id="form-container"></div> <Script src="https://your-cms-form-script-url.js" onLoad={initForm} /> </> ); }
核心思路都是确保每次回到页面时,脚本要么重新加载,要么初始化逻辑被重新调用,同时保证表单容器是脚本可识别的有效DOM节点。
内容的提问来源于stack exchange,提问作者ComCool
相关产品推荐
相关产品推荐

