React-stripe-elements: Getting context injection error when using injectStripe HoC

Created on 17 Jul 2017  路  5Comments  路  Source: stripe/react-stripe-elements

I'm willing to assume this is just my ignorance on how context works in React, but I'm confused why I am receiving this error

It looks like you are trying to inject Stripe context outside of an Elements context.
Please be sure the component that calls createSource or createToken is within an 
<Elements> component.

This is what my code looks like (here's a running example).

class _CardForm extends React.Component {
  render () {
    return (
      <div className="Checkout">
        <h1>Available Elements</h1>
        <Elements>
          <form onSubmit={this.props.stripe.createToken()}>
            <label>
              Card details
              <CardElement />
            </label>
            <button>Pay</button>
          </form>
        </Elements>
      </div>
    )
  }
}

const CardForm = injectStripe(_CardForm)

const App = () => 
  <StripeProvider apiKey="pk_RXwtgk4Z5VR82S94vtwmam6P8qMXQ">
    <CardForm />
  </StripeProvider>

ReactDOM.render(<App />, document.querySelector('.App'))

AFAICT, I am definitely trying to "inject Stripe context inside of an Elements context", not outside. I can't see what I'm doing that is breaking the code 馃槙.

Any help would be greatly appreciated!

Most helpful comment

So I think I figured out why the above code doesn't work.

Tl;dr

If you want to use the injectStripe HOC, you cannot do so on a component that renders <Elements> directly. You must pull out the code that <Elements> wraps into it's own component and use injectStripe on that before nesting it within <Elements>.

Details

This example works fine

class _CardForm extends React.Component {
  render() {
    return (
      <form onSubmit={() => this.props.stripe.createToken().then(payload => console.log(payload))}>
        <label>
          Card details
          <CardElement />
        </label>
        <button>Pay</button>
      </form>
    )
  }
}
const CardForm = injectStripe(_CardForm)

class Checkout extends React.Component {
  render() {
    return (
      <div className="Checkout">
        <h1>Available Elements</h1>
        <Elements>
          <CardForm />
        </Elements>
      </div>
    )
  }
}
const App = () => {
  return (
    <StripeProvider apiKey="pk_RXwtgk4Z5VR82S94vtwmam6P8qMXQ">
      <Checkout />
    </StripeProvider>
  )
}
ReactDOM.render(<App />, document.querySelector('.App'))

Notice that the only difference between this chunk of code and the code in the original issue description is that I've pulled out the wrapping <Elements> code into a new component called <Checkout />.

Unless I am missing something, it would appear that if you want to use injectStripe, you cannot do so on a component that renders <Elements> directly. You must pull out the code that <Elements> wraps into it's own component.

I suppose this makes sense, since the component rendered within <Elements> is injected with the stripe prop at build time, before it actually knows that the code making use of stripe is rendered within <Elements>.

I'd be happy to submit a PR for it if this is something y'all would like more explicit documentation on.

All 5 comments

So I think I figured out why the above code doesn't work.

Tl;dr

If you want to use the injectStripe HOC, you cannot do so on a component that renders <Elements> directly. You must pull out the code that <Elements> wraps into it's own component and use injectStripe on that before nesting it within <Elements>.

Details

This example works fine

class _CardForm extends React.Component {
  render() {
    return (
      <form onSubmit={() => this.props.stripe.createToken().then(payload => console.log(payload))}>
        <label>
          Card details
          <CardElement />
        </label>
        <button>Pay</button>
      </form>
    )
  }
}
const CardForm = injectStripe(_CardForm)

class Checkout extends React.Component {
  render() {
    return (
      <div className="Checkout">
        <h1>Available Elements</h1>
        <Elements>
          <CardForm />
        </Elements>
      </div>
    )
  }
}
const App = () => {
  return (
    <StripeProvider apiKey="pk_RXwtgk4Z5VR82S94vtwmam6P8qMXQ">
      <Checkout />
    </StripeProvider>
  )
}
ReactDOM.render(<App />, document.querySelector('.App'))

Notice that the only difference between this chunk of code and the code in the original issue description is that I've pulled out the wrapping <Elements> code into a new component called <Checkout />.

Unless I am missing something, it would appear that if you want to use injectStripe, you cannot do so on a component that renders <Elements> directly. You must pull out the code that <Elements> wraps into it's own component.

I suppose this makes sense, since the component rendered within <Elements> is injected with the stripe prop at build time, before it actually knows that the code making use of stripe is rendered within <Elements>.

I'd be happy to submit a PR for it if this is something y'all would like more explicit documentation on.

Awesome, I'm glad you figured it out :). That's exactly right. A PR for docs would be great!

@indiesquidge
I've set up my checkout component form using react-stripe-elements' and my onsubmit handler is returning the stripe token. I'm just not sure what I'm supposed to do now?

  1. Does react-stripe-elements handle the API call for making the payment for me using my test API key?
  2. Or do I need to take the token and do the API call myself using the token that's returned?

@rdalfonso once you get the token, you need to send it to your backend, which should call the Stripe API at /v1/charges. You can use one of our server side bindings to help you do this. More instructions in our docs here: https://stripe.com/docs/charges.

@atty-stripe - I came to that same conclusion after re-re-reading the documentation. Thought I could make an API call from the browser. Problem is solved. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kongakong picture kongakong  路  4Comments

shortcircuit3 picture shortcircuit3  路  5Comments

iMerica picture iMerica  路  5Comments

alenadrex picture alenadrex  路  3Comments

stephenhuh picture stephenhuh  路  4Comments