New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use react-stripe-js? #16037
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
A codesandbox that demonstrates how to do the integration: https://codesandbox.io/s/stripe-0xez4 with
App.tsx import * as React from "react";
import Container from "@mui/material/Container";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import CreditCardDetail from "./CreditCardDetail";
const stripePromise = loadStripe("pk_test_ju6veMmqd5eDMe1XhQVPyze2");
export default function App() {
return (
<Container maxWidth="sm" sx={{ my: 4 }}>
<Elements stripe={stripePromise}>
<CreditCardDetail />
</Elements>
</Container>
);
} CreditCardDetail.tsx import * as React from "react";
import Grid from "@mui/material/Grid";
import {
StripeTextFieldNumber,
StripeTextFieldExpiry,
StripeTextFieldCVC
} from "./commonTextFields";
export default function CreditCardDetail() {
const [state, setState] = React.useState({
cardNumberComplete: false,
expiredComplete: false,
cvcComplete: false,
cardNumberError: null,
expiredError: null,
cvcError: null
});
const onElementChange = (field, errorField) => ({
complete,
error = { message: null }
}) => {
setState({ ...state, [field]: complete, [errorField]: error.message });
};
const { cardNumberError, expiredError, cvcError } = state;
return (
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<StripeTextFieldNumber
error={Boolean(cardNumberError)}
labelErrorMessage={cardNumberError}
onChange={onElementChange("cardNumberComplete", "cardNumberError")}
/>
</Grid>
<Grid item xs={6} sm={3}>
<StripeTextFieldExpiry
error={Boolean(expiredError)}
labelErrorMessage={expiredError}
onChange={onElementChange("expiredComplete", "expiredError")}
/>
</Grid>
<Grid item xs={6} sm={3}>
<StripeTextFieldCVC
error={Boolean(cvcError)}
labelErrorMessage={cvcError}
onChange={onElementChange("cvcComplete", "cvcError")}
/>
</Grid>
<pre>{JSON.stringify(state, null, 2)}</pre>
</Grid>
);
} commonTextFields.tsx import * as React from "react";
import {
AuBankAccountElement,
CardCvcElement,
CardExpiryElement,
CardNumberElement,
FpxBankElement,
IbanElement,
IdealBankElement
} from "@stripe/react-stripe-js";
import TextField, { TextFieldProps } from "@mui/material/TextField";
import StripeInput from "./StripeInput";
type StripeElement =
| typeof AuBankAccountElement
| typeof CardCvcElement
| typeof CardExpiryElement
| typeof CardNumberElement
| typeof FpxBankElement
| typeof IbanElement
| typeof IdealBankElement;
interface StripeTextFieldProps<T extends StripeElement>
extends Omit<TextFieldProps, "onChange" | "inputComponent" | "inputProps"> {
inputProps?: React.ComponentProps<T>;
labelErrorMessage?: string;
onChange?: React.ComponentProps<T>["onChange"];
stripeElement?: T;
}
export const StripeTextField = <T extends StripeElement>(
props: StripeTextFieldProps<T>
) => {
const {
helperText,
InputLabelProps,
InputProps = {},
inputProps,
error,
labelErrorMessage,
stripeElement,
...other
} = props;
return (
<TextField
fullWidth
InputLabelProps={{
...InputLabelProps,
shrink: true
}}
error={error}
InputProps={{
...InputProps,
inputProps: {
...inputProps,
...InputProps.inputProps,
component: stripeElement
},
inputComponent: StripeInput
}}
helperText={error ? labelErrorMessage : helperText}
{...(other as any)}
/>
);
};
export function StripeTextFieldNumber(
props: StripeTextFieldProps<typeof CardNumberElement>
) {
return (
<StripeTextField
label="Credit Card Number"
stripeElement={CardNumberElement}
{...props}
/>
);
}
export function StripeTextFieldExpiry(
props: StripeTextFieldProps<typeof CardExpiryElement>
) {
return (
<StripeTextField
label="Expires"
stripeElement={CardExpiryElement}
{...props}
/>
);
}
export function StripeTextFieldCVC(
props: StripeTextFieldProps<typeof CardCvcElement>
) {
return (
<StripeTextField
label="CVC Code"
stripeElement={CardCvcElement}
{...props}
/>
);
} import * as React from "react";
import { alpha, useTheme } from "@mui/material/styles";
import { InputBaseComponentProps } from "@mui/material/InputBase";
const StripeInput = React.forwardRef<any, InputBaseComponentProps>(
function StripeInput(props, ref) {
const { component: Component, options, ...other } = props;
const theme = useTheme();
const [mountNode, setMountNode] = React.useState<any | null>(null);
React.useImperativeHandle(
ref,
() => ({
focus: () => mountNode.focus()
}),
[mountNode]
);
return (
<Component
onReady={setMountNode}
options={{
...options,
style: {
base: {
color: theme.palette.text.primary,
fontSize: "16px",
lineHeight: "1.4375em", // 23px
fontFamily: theme.typography.fontFamily,
"::placeholder": {
color: alpha(theme.palette.text.primary, 0.42)
}
},
invalid: {
color: theme.palette.text.primary
}
}
}}
{...other}
/>
);
}
);
export default StripeInput; A related issue: stripe-archive/react-stripe-elements#164. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
#16037 (comment) wasn't working for me with the following:
The issue is that MUI is attempting to pass in a prop named
Anyways, here is the code: commonTextFields.tsx
CreditCardDetail.tsx
StripeInput.tsx
|
I believe this issue has occurred for v5. TextField |
This comment was marked as resolved.
This comment was marked as resolved.
For MUI v5 I had to wrap the StripeInputComponent in React.forwardRef, per https://mui.com/material-ui/react-text-field/#integration-with-3rd-party-input-libraries Like this
|
When changing any Stripe input the InputBase.js produces an error in the dirtyCheck when trying to access the value of either the inputRef.current or target.value:
Cannot read property 'value' of undefined
Expected Behavior 🤔
Input should update normally
Current Behavior 😯
Produces error and prevents using input
Steps to Reproduce 🕹
Link: https://codesandbox.io/s/createreactapp-1e4fe
Cannot read property 'value' of undefined
Context 🔦
Error causes inability to proceed in payment screen
Your Environment 🌎
The text was updated successfully, but these errors were encountered: