Next.js 13中Stripe Elements客户端组件的报错与类型问题求助
问题背景
我在Next.js 13应用中集成Stripe支付功能,使用Elements组件包裹表单时触发了"use client"相关错误。我是Next.js和TypeScript新手,以下是我的代码及问题详情:
初始代码(layout.tsx)
import { loadStripe } from "@stripe/stripe-js" import { Inconsolata, Mukta } from "next/font/google" import SubscriptionModal from "./components/modals/SubscriptionModal" import Navbar from "./components/navbar/Navbar" import "./globals.css" import ToastProvider from "./providers/ToastProvider" import { Elements } from "@stripe/react-stripe-js" const stripePromise = loadStripe( process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY! ) const inconsolata = Inconsolata({ subsets: ["latin"] }) const mukta = Mukta({ weight: "500", subsets: ["latin"] }) export const metadata = { title: "Subscription App", description: "Generated by create next app", } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body className={inconsolata.className}> <header className={mukta.className}> <Navbar /> </header> <Elements stripe={stripePromise}> <SubscriptionModal /> </Elements> <ToastProvider /> {children} </body> </html> ) }
第一阶段错误
直接在RootLayout中使用Elements组件时,触发了"use client"相关错误。
尝试的解决方案
我按照提示创建了StripeProvider组件,将Elements包裹在"use client"指令中:
修改后的layout.tsx
import { loadStripe } from "@stripe/stripe-js" import { Inconsolata, Mukta } from "next/font/google" import StripeProvider from "../app/providers/StripeProvider" import SubscriptionModal from "./components/modals/SubscriptionModal" import Navbar from "./components/navbar/Navbar" import "./globals.css" import ToastProvider from "./providers/ToastProvider" const stripePromise = loadStripe( process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY! ) const inconsolata = Inconsolata({ subsets: ["latin"] }) const mukta = Mukta({ weight: "500", subsets: ["latin"] }) export const metadata = { title: "Subscription App", description: "Generated by create next app", } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body className={inconsolata.className}> <header className={mukta.className}> <Navbar /> </header> <StripeProvider stripePromise={stripePromise}> <SubscriptionModal /> </StripeProvider> <ToastProvider /> {children} </body> </html> ) }
StripeProvider.tsx
"use client" import { Elements } from "@stripe/react-stripe-js" import Stripe from "stripe" interface StripeProviderProps { stripePromise: Stripe | null | PromiseLike<Stripe | null> children: React.ReactNode } const StripeProvider: React.FC<StripeProviderProps> = ({ stripePromise, children }) => { return <Elements stripe={stripePromise}>{children}</Elements> } export default StripeProvider
新的类型错误
修改后,StripeProvider.tsx中Elements组件的stripe属性出现类型不匹配错误:
Type 'import("stripe").Stripe | PromiseLike<import("stripe").Stripe | null> | null' is not assignable to type 'import("/home/dexter-ubuntu/webdev/next-prjs/next-13-prjs/subscription-app/node_modules/@stripe/stripe-js/types/stripe-js/stripe").Stripe | PromiseLike<import("/home/dexter-ubuntu/webdev/next-prjs/next-13-prjs/subscription-app/node_modules/@stripe/stripe-js/types/stripe-js/stripe").Stripe | null> | null'.
Type 'Stripe' is not assignable to type 'Stripe | PromiseLike<Stripe | null> | null'.ts(2322)
react-stripe.d.ts(666, 5): The expected type comes from property 'stripe' which is declared here on type 'IntrinsicAttributes & ElementsProps & { children?: ReactNode; }'
我参考Stripe React文档设置了stripePromise的类型(Stripe | null | Promise<Stripe | null>),但显然类型声明存在问题。
补充尝试
- 看到示例中使用
await loadStripe(),但RootLayout不是异步函数,无法直接使用该写法。 - 注释掉
Elements组件后应用可正常运行,仓库代码可复现问题。
内容的提问来源于stack exchange,提问作者Avinash Kumar

