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

NextJS中如何让useSWR仅在页面加载时调用一次API?

问题:Next.js中使用useSWR获取Stripe Payment Intent重复请求的解决办法

我正在NextJS中自定义Stripe支付表单,需要创建Payment Intent并调用API获取client secret。使用useSWR和axios实现时,当前配置会重复请求API,希望页面加载时仅调用一次API。

我的代码如下:

const BillingPage = () => {
    const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);

    const {data: intent, error, mutate} = useSWR('/api/stripe-intent', () => 
        axios.get('/api/stripe-intent')
            .then(response => response.data)
    )

    if (! intent) {
        return (<LoadPageComponent />)
    }

    const options = {
        clientSecret: intent?.client_secret,
    }

    return (
        <>
            <p>Payment form here</p>
        </>
    )
}

解决方法

方法1:调整useSWR的重验证配置

useSWR默认会在页面聚焦、重新连接网络或数据过时时自动重验证请求,通过关闭这些特性可以实现仅首次加载时请求一次:

const {data: intent, error, mutate} = useSWR('/api/stripe-intent', () => 
    axios.get('/api/stripe-intent')
        .then(response => response.data),
    {
        revalidateIfStale: false,
        revalidateOnFocus: false,
        revalidateOnReconnect: false
    }
)
  • revalidateIfStale: 设为false,避免数据过时时自动重请求
  • revalidateOnFocus: 设为false,避免页面重新聚焦时重请求
  • revalidateOnReconnect: 设为false,避免网络重新连接时重请求

这种方式保留了useSWR的缓存能力,后续如果需要手动刷新数据,依然可以调用mutate()方法。

方法2:改用useEffect实现单次请求

如果不需要useSWR的缓存、重新验证等特性,直接用useEffect配合useState也能实现页面挂载时仅请求一次:

const BillingPage = () => {
    const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
    const [intent, setIntent] = useState(null);
    const [error, setError] = useState(null);

    useEffect(() => {
        const fetchPaymentIntent = async () => {
            try {
                const response = await axios.get('/api/stripe-intent');
                setIntent(response.data);
            } catch (err) {
                setError(err);
            }
        };
        fetchPaymentIntent();
    }, []); // 空依赖数组确保仅组件挂载时执行一次

    if (! intent) {
        return (<LoadPageComponent />)
    }

    const options = {
        clientSecret: intent?.client_secret,
    }

    return (
        <>
            <p>Payment form here</p>
        </>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:42:05