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

如何判断React项目中stripe-pricing-table脚本的加载状态?

解决Next.js中Stripe定价表加载时的白框闪烁问题

针对你在Next.js集成Stripe定价表时遇到的iframe加载闪烁问题,这里提供两种可行的解决方案:


方案一:手动加载脚本并监听加载状态

跳过在_document.tsx的<Head>中添加脚本的步骤,改为在组件内手动加载Stripe定价表脚本,通过监听脚本的onload事件控制组件渲染时机,同时显示自定义加载占位符:

import { useState, useEffect } from 'react';

export default function PricingPage() {
  const [stripeScriptReady, setStripeScriptReady] = useState(false);

  useEffect(() => {
    // 避免重复加载脚本
    const existingScript = document.getElementById('stripe-pricing-script');
    if (existingScript) {
      setStripeScriptReady(true);
      return;
    }

    const script = document.createElement('script');
    script.id = 'stripe-pricing-script';
    script.src = 'https://js.stripe.com/v3/pricing-table.js';
    script.async = true;

    // 脚本加载完成后更新状态
    script.onload = () => setStripeScriptReady(true);
    // 处理加载失败的情况
    script.onerror = () => console.error('Stripe定价表脚本加载失败');

    document.head.appendChild(script);

    // 组件卸载时清理脚本
    return () => document.head.removeChild(script);
  }, []);

  return (
    <div className="pricing-wrapper">
      {!stripeScriptReady ? (
        {/* 自定义加载占位符,比如骨架屏 */}
        <div className="pricing-skeleton">
          <div className="skeleton-card"></div>
          <div className="skeleton-card"></div>
          <div className="skeleton-card"></div>
        </div>
      ) : (
        <stripe-pricing-table
          pricing-table-id="你的定价表ID"
          publishable-key="你的可发布密钥"
        ></stripe-pricing-table>
      )}
    </div>
  );
}

搭配基础骨架屏样式(可根据你的页面风格调整):

.pricing-skeleton {
  display: flex;
  gap: 1rem;
  padding: 2rem;
}
.skeleton-card {
  width: 300px;
  height: 400px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
  border-radius: 8px;
}
@keyframes loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

方案二:监听生成的iframe加载状态

如果你仍想保留_document.tsx中添加脚本的方式,可以通过MutationObserver监听<stripe-pricing-table>元素的子节点变化,找到生成的iframe后监听其onload事件,通过透明度过渡避免闪烁:

import { useState, useEffect, useRef } from 'react';

export default function PricingPage() {
  const [isIframeLoading, setIsIframeLoading] = useState(true);
  const pricingTableRef = useRef<HTMLElement>(null);

  useEffect(() => {
    const observer = new MutationObserver((mutations) => {
      mutations.forEach(mutation => {
        const iframe = pricingTableRef.current?.querySelector('iframe');
        if (iframe) {
          iframe.onload = () => {
            setIsIframeLoading(false);
            observer.disconnect(); // 完成后停止监听
          };
        }
      });
    });

    if (pricingTableRef.current) {
      observer.observe(pricingTableRef.current, { childList: true, subtree: true });
    }

    return () => observer.disconnect();
  }, []);

  return (
    <div className="pricing-wrapper">
      {isIframeLoading && (
        <div className="loading-overlay">
          <p>加载定价表中...</p>
        </div>
      )}
      <div 
        ref={pricingTableRef}
        style={{ 
          opacity: isIframeLoading ? 0 : 1,
          transition: 'opacity 0.3s ease-in-out',
          position: 'relative'
        }}
      >
        <stripe-pricing-table
          pricing-table-id="你的定价表ID"
          publishable-key="你的可发布密钥"
        ></stripe-pricing-table>
      </div>
    </div>
  );
}

核心思路

两种方案都是通过延迟渲染定价表/控制显示状态,替换默认的白框加载过程。你可以根据项目需求选择其中一种:

  • 方案一更适合需要严格控制脚本加载时机的场景;
  • 方案二则兼容原有_document.tsx的脚本配置方式。

内容的提问来源于stack exchange,提问作者Davis Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:01:19