Stripe具有react-stripe-elements,提供injectStripe HOC。我们现在在2019年,而HOC不再那么酷了。 Stripe似乎并不着急,我认为这是因为他们想支持旧版本的React,因此只在寻找最低的公分母解决方案。

我正在寻找一种通过 Hook (而不是stripe提供的 Prop )获取injectStripe的方法。

用法看起来像这样const stripe = useStripe()这样以后我就可以使用stripe.handleCardSetup和其他API方法

import { CardElement } from 'react-stripe-elements'

const CardForm = ({secret}) => {
  const stripe = useStripe()

  const handleSubmit = async () => {
    const { setupIntent, error } = await stripe.handleCardSetup(secret)
    // ...
  }

  return (
    <>
      <CardElement />
      <button onClick={handleSubmit} />
    </>
  )
}

您如何从现有的API和组件中定义useStripe Hook ?stripe应该与使用injectStripe钩子(Hook)时获得的内容相同

GH的相关问题:API Review: Hooks & Beyond

最佳答案

经过一堆反复试验后,我得出了这个结论,这很简单。这是采用条纹偷看和其他需要useStripe钩子(Hook)的人

// StripeHookProvider.jsx

import React, { useContext, createContext } from 'react'
import { injectStripe } from 'react-stripe-elements'

const Context = createContext()

export const useStripe = () => useContext(Context)

const HookProvider = ({ children, stripe }) => {
  return <Context.Provider value={stripe}>{children}</Context.Provider>
}

export default injectStripe(HookProvider)

像这样导入StripeHookProvider并将其添加到您的组件层次结构中。注意:因为它依赖injectStripe,所以它必须是<Elements>的子级
    <StripeProvider {...{ stripe }}>
      <Elements>
        <StripeHookProvider>
          <MyForm />
        </StripeHookProvider>
      </Elements>
    </StripeProvider>

然后在MyForm中使用它像这样

// MyForm.jsx
import { useStripe } from './StripeHookProvider'

const MyForm = () => {
  const stripe = useStripe()

  const handleSubmit = () => {
    const { setupIntent, error } = await stripe.handleCardSetup(secret ... // and so on
  }
}

这样,您只需要在一个地方进行injectStripe即可,并且将其整齐地藏在视线之外。从该代码中可以看到,这不是火箭科学,对于条纹偷看者来说,将其添加到他们的代码中应该不是问题,因为它们在上下文中的某个地方对<StripeHookProvider>对象的引用,因此希望完全消除stripe

我尝试了很多方法,但这是唯一可行的方法。我没有深入研究Stripe的JS代码来了解发生了什么,但是唯一可以使用的是从stripe获得的injectStripe。您通过window.Stripe(apiKey)设置的代码不相同,并且由于无法正确观察<Elements>而无法正常工作,因此它不知道表单的状态。

也许,必须在injectStripe的子级上使用<Elements>的原因与Stripe团队花一些时间来构建此 Hook 的原因相同。

09-25 19:01