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

开发正常但部署Vercel时出现usePayPalScriptReducer报错求助

问题原因及解决方案

核心原因

你遇到的usePayPalScriptReducer must be used within a PayPalScriptProvider错误,和getStaticPaths/getStaticProps的静态生成机制直接相关:

  • 开发环境中,Next.js默认以客户端渲染为主,PayPal组件的代码在浏览器中执行,PayPalScriptProvider能正常包裹PayPalButtons,钩子可以正常工作。
  • 部署到Vercel时,getStaticProps会触发服务器端预渲染,页面在构建阶段就会被生成静态HTML。此时PayPalButtons内部的usePayPalScriptReducer钩子会在服务器端执行,但服务器端没有PayPalScriptProvider的上下文(Provider仅在客户端 hydration 时才会挂载),因此抛出错误。

解决方案

方案1:标记组件为客户端组件(Next.js 13+)

在你的Join组件顶部添加'use client'指令,强制该组件仅在客户端执行,避免服务器端预渲染时触发PayPal的钩子:

'use client' // 新增这一行
import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js'
import {
  getAllBootcampsSlugs,
  getBootcampDataBySlug,
} from './../../../src/utils/bootcampsApi'

// 后续组件代码保持不变
function Join() {
  function createOrder(data, actions) {
    return actions.order
      .create({
        purchase_units: [
          {
            amount: {
              value: 5,
            },
          },
        ],
        application_context: {
          shipping_preference: 'NO_SHIPPING',
        },
      })
      .then((orderID) => {
        return orderID
      })
  }

  async function onApprove(data, actions) {
    // 你的支付确认逻辑
  }

  function onError(data, actions) {
    // 你的错误处理逻辑
  }

  return (
    <div className="min-h-screen flex flex-col justify-center items-center">
      <PayPalScriptProvider
        options={{
          'client-id': process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,
        }}>
        <PayPalButtons
          style={{
            color: 'black',
            label: 'pay',
            tagline: false,
          }}
          createOrder={createOrder}
          onApprove={onApprove}
          onError={onError}
        />
      </PayPalScriptProvider>
    </div>
  )
}

// ...getStaticPaths和getStaticProps保持不变

方案2:动态导入并禁用SSR(兼容旧版Next.js)

如果使用的是Next.js 12及以下版本,或者不想标记整个页面为客户端组件,可以将PayPal相关逻辑抽成独立组件,然后通过动态导入禁用服务器端渲染:

  1. 新建PayPalCheckout.js组件:
import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js'

export default function PayPalCheckout() {
  function createOrder(data, actions) {
    return actions.order
      .create({
        purchase_units: [
          {
            amount: {
              value: 5,
            },
          },
        ],
        application_context: {
          shipping_preference: 'NO_SHIPPING',
        },
      })
      .then((orderID) => {
        return orderID
      })
  }

  async function onApprove(data, actions) {
    // 你的支付确认逻辑
  }

  function onError(data, actions) {
    // 你的错误处理逻辑
  }

  return (
    <PayPalScriptProvider
      options={{
        'client-id': process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID,
      }}>
      <PayPalButtons
        style={{
          color: 'black',
          label: 'pay',
          tagline: false,
        }}
        createOrder={createOrder}
        onApprove={onApprove}
        onError={onError}
      />
    </PayPalScriptProvider>
  )
}
  1. 修改原Join页面,动态导入该组件:
import dynamic from 'next/dynamic'
import {
  getAllBootcampsSlugs,
  getBootcampDataBySlug,
} from './../../../src/utils/bootcampsApi'

// 动态导入并禁用SSR
const PayPalCheckout = dynamic(() => import('./PayPalCheckout'), {
  ssr: false,
})

function Join({ data }) {
  return (
    <div className="min-h-screen flex flex-col justify-center items-center">
      <PayPalCheckout />
    </div>
  )
}

export default Join

Join.getLayout = (page) => page

export async function getStaticPaths() {
  const paths = getAllBootcampsSlugs().map((bootcamp) => ({
    params: {
      bootcamp,
    },
  }))
  return {
    paths,
    fallback: false,
  }
}

export async function getStaticProps(context) {
  const { params } = context
  const data = getBootcampDataBySlug(params.bootcamp)
  return {
    props: {
      data: data,
    },
  }
}

验证

修改后重新部署到Vercel,静态生成过程中不会再执行PayPal组件的服务器端代码,客户端渲染时PayPalScriptProvider会正常提供上下文,错误即可解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:25:27