Next.js客户端路由下Xola嵌入组件加载异常及无限刷新问题
解决Next.js客户端路由下Xola嵌入组件不加载的问题
问题分析
当前代码里的window.location.reload()会触发客户端渲染→页面刷新→SSR重新渲染→再触发客户端刷新的无限循环。而Xola组件不加载的核心原因是:Xola的嵌入脚本仅在页面首次加载时扫描DOM并初始化组件,但Next.js客户端路由是单页跳转,不会重新执行脚本,所以新渲染的Xola容器元素无法被初始化。
解决方案
1. 移除无限刷新逻辑
首先删掉{isSsr ? null : window.location.reload()},终止循环。
2. 手动触发Xola组件初始化
通过useEffect监听路由完成事件,在组件挂载/路由切换后,手动加载Xola脚本并调用官方初始化方法,确保新渲染的DOM元素被识别。
修改后的代码示例
checkout.js
import Head from "next/head"; import { useRouter } from "next/router"; import { Container, Button } from "@mui/material"; import { makeStyles } from "@mui/styles"; import { CheckoutCard } from "../components/layout/directory"; import { useEffect, useRef } from "react"; function Checkout() { const router = useRouter(); const classes = useStyles(); const xolaScriptLoaded = useRef(false); // 标记脚本是否已加载 useEffect(() => { const initXolaCheckout = () => { // 优先调用Xola官方初始化方法 if (window.Xola) { window.Xola.initEmbeds(); } else { // 未加载脚本则动态插入 const script = document.createElement('script'); script.src = 'https://xola.com/js/embed.js'; script.async = true; script.onload = () => { xolaScriptLoaded.current = true; window.Xola?.initEmbeds(); }; document.body.appendChild(script); } }; // 路由切换完成后触发初始化 const handleRouteChange = () => initXolaCheckout(); router.events.on('routeChangeComplete', handleRouteChange); // 组件挂载时初始化一次 initXolaCheckout(); // 清理事件监听 return () => router.events.off('routeChangeComplete', handleRouteChange); }, [router]); return ( <> <Head> <title>checkout</title> </Head> <Container className={classes.root}> <Button className={classes.btn} onClick={router.back} color="secondary" variant="contained" > back </Button> <CheckoutCard /> </Container> </> ); } const useStyles = makeStyles((theme) => ({ root: { marginTop: theme.spacing(10) }, btn: { marginBottom: theme.spacing(5) }, })); export default Checkout;
CheckoutCard.js(保持原结构无需修改)
function CheckoutCard() { return ( <div className="xola-embedded-checkout" data-seller="5f3d889683cfdc77b119e592" data-experience="5f3d8d80d6ba9c6b14748160" data-version="2" id="xola-checkout" ></div> ); } export default CheckoutCard;
关键说明
- 动态加载脚本:用
useRef标记脚本加载状态,避免全局重复插入脚本。 - 路由事件监听:监听
routeChangeComplete确保客户端路由跳转后,新DOM能被Xola初始化。 - 官方API调用:
window.Xola.initEmbeds()是Xola嵌入脚本的标准方法,用于重新扫描DOM并初始化所有嵌入组件,比强制刷新页面更高效可靠。
备选方案(若Xola无公开初始化方法)
如果Xola未提供官方初始化API,可以通过更新组件key强制重新挂载容器,触发脚本的自动扫描:
import { useState, useEffect } from "react"; import { useRouter } from "next/router"; function CheckoutCard() { const router = useRouter(); const [componentKey, setComponentKey] = useState(Date.now()); useEffect(() => { const handleRouteChange = () => setComponentKey(Date.now()); router.events.on('routeChangeComplete', handleRouteChange); return () => router.events.off('routeChangeComplete', handleRouteChange); }, [router]); return ( <div key={componentKey} className="xola-embedded-checkout" data-seller="5f3d889683cfdc77b119e592" data-experience="5f3d8d80d6ba9c6b14748160" data-version="2" id="xola-checkout" ></div> ); }
内容的提问来源于stack exchange,提问作者Tyler Miller
相关产品推荐
相关产品推荐

