@@ -223,16 +223,11 @@ export interface EmbeddedPaymentElementConfiguration {
223223 opensCardScannerAutomatically ?: boolean ;
224224}
225225
226- // `IntentConfiguration` requires `mode`; `Checkout` always has `sessionKey`
227- // and never has `mode`. Check both so a stray object with a `sessionKey`
228- // field doesn't get classified as a Checkout handle. We use `in` rather
229- // than property access so we don't trigger the throwing `sessionKey`
230- // getter on an unloaded handle.
231- const isCheckout = ( intent : unknown ) : intent is Checkout =>
232- typeof intent === 'object' &&
233- intent !== null &&
234- 'sessionKey' in intent &&
235- ! ( 'mode' in intent ) ;
226+ // `Checkout` has `sessionKey`, `IntentConfiguration` has `mode`. We use `in`
227+ // to avoid tripping the throwing `sessionKey` getter on an unloaded handle.
228+ const isCheckoutSession = (
229+ value : PaymentSheetTypes . IntentConfiguration | Checkout
230+ ) : value is Checkout => 'sessionKey' in value && ! ( 'mode' in value ) ;
236231
237232// -----------------------------------------------------------------------------
238233// Embedded API
@@ -285,7 +280,7 @@ async function createEmbeddedPaymentElement(
285280) : Promise < EmbeddedPaymentElement > {
286281 setupConfigurationHandlers ( configuration ) ;
287282
288- if ( isCheckout ( intent ) ) {
283+ if ( isCheckoutSession ( intent ) ) {
289284 await NativeStripeSdkModule . createEmbeddedPaymentElementWithCheckout (
290285 intent . sessionKey ,
291286 configuration
@@ -454,30 +449,25 @@ export function useEmbeddedPaymentElement(
454449 configuration : EmbeddedPaymentElementConfiguration
455450) : UseEmbeddedPaymentElementResult ;
456451/**
457- * Initializes an `EmbeddedPaymentElement` from a Checkout session .
452+ * Initializes an `EmbeddedPaymentElement` from a Stripe Checkout Session .
458453 *
459- * The `checkout` argument must be a loaded handle (i.e. `state.status === 'loaded'`
460- * from `useCheckout`). Because hooks must be called unconditionally, gate the
461- * consuming component on the loaded state and pass the handle into a child
462- * component, e.g.:
454+ * Pass a loaded handle from `useCheckout`. Render the consumer in a child
455+ * component so the hook only runs once `state.status === 'loaded'`.
463456 *
464457 * @example
465- * function CheckoutScreen() {
466- * const { checkout, state, error } = useCheckout(clientSecret);
467- * if (error) return <ErrorView error={error} />;
468- * if (state?.status !== 'loaded') return <Loading />;
469- * return <EmbeddedView checkout={checkout} />;
458+ * function Cart() {
459+ * const { checkout, state } = useCheckout(clientSecret);
460+ * if (state?.status !== 'loaded') return null;
461+ * return <EmbeddedCheckout checkout={checkout} />;
470462 * }
471463 *
472- * function EmbeddedView ({ checkout }: { checkout: Checkout }) {
464+ * function EmbeddedCheckout ({ checkout }: { checkout: Checkout }) {
473465 * const { embeddedPaymentElementView } =
474466 * useEmbeddedPaymentElement(checkout, configuration);
475467 * return embeddedPaymentElementView;
476468 * }
477469 *
478- * @param checkout - A loaded `Checkout` handle from `useCheckout`. Accessing
479- * `checkout.sessionKey` (which this hook does internally) throws if the
480- * session has not finished loading.
470+ * @param checkout - A loaded `Checkout` handle from `useCheckout`.
481471 * @param configuration - Configuration for the embedded element.
482472 */
483473export function useEmbeddedPaymentElement (
@@ -512,14 +502,9 @@ export function useEmbeddedPaymentElement(
512502 return ref . current ;
513503 }
514504
515- // For Checkout the dep collapses to the session key string so we don't
516- // re-create the element when only the handle reference changes. For
517- // IntentConfiguration the dep is the intent object itself.
518- const intentKey : string | PaymentSheetTypes . IntentConfiguration = isCheckout (
519- intent
520- )
521- ? intent . sessionKey
522- : intent ;
505+ // Re-key on the session key (Checkout) or intent object so we only
506+ // recreate the element when the source actually changes.
507+ const intentKey = isCheckoutSession ( intent ) ? intent . sessionKey : intent ;
523508 const intentRef = useRef ( intent ) ;
524509 intentRef . current = intent ;
525510
@@ -578,6 +563,7 @@ export function useEmbeddedPaymentElement(
578563
579564 // Render the embedded view
580565 const embeddedPaymentElementView = useMemo ( ( ) => {
566+ // `intentKey` is the session key string for Checkout, the IntentConfiguration object otherwise.
581567 const intentProps =
582568 typeof intentKey === 'string'
583569 ? { checkout : { sessionKey : intentKey } }
0 commit comments