Javascript 盖茨比,Stripe:创建按钮源代码返回';未捕获类型错误:无法读取属性';配置';未定义的';

Javascript 盖茨比,Stripe:创建按钮源代码返回';未捕获类型错误:无法读取属性';配置';未定义的';,javascript,reactjs,stripe-payments,gatsby,Javascript,Reactjs,Stripe Payments,Gatsby,我正在建立一个电子商务网站的基础上从一个教程条目 但是,从checkout.js的源代码返回这些错误,整个页面都是白色的 Uncaught TypeError: Cannot read property 'configure' of undefined The above error occurred in the <Checkout> component: The above error occurred in the <LocationProvider> compon

我正在建立一个电子商务网站的基础上从一个教程条目

但是,从checkout.js的源代码返回这些错误,整个页面都是白色的

Uncaught TypeError: Cannot read property 'configure' of undefined
The above error occurred in the <Checkout> component:
The above error occurred in the <LocationProvider> component:
GET http://localhost:8000/.../src/components/checkout.js 404 (Not Found)
相关信息:

此外,我在教程中使用完全相同的代码制作index.js进行了测试,但结果与上面的相同。 当我禁用checkout.js组件时,它工作得非常好,这意味着我打赌checkout.js代码具有最高的修复潜力

src/components/checkout.js

import React from "react"

// hardcoded amount (in US cents) to charge users
// you could set this variable dynamically to charge different amounts
const amount = 2500
const cardStyles = {
  display: "flex",
  flexDirection: "column",
  justifyContent: "space-around",
  alignItems: "flex-start",
  padding: "3rem",
  boxShadow: "5px 5px 25px 0 rgba(46,61,73,.2)",
  backgroundColor: "#fff",
  borderRadius: "6px",
  maxWidth: "400px",
}
const buttonStyles = {
  fontSize: "13px",
  textAlign: "center",
  color: "#fff",
  outline: "none",
  padding: "12px 60px",
  boxShadow: "2px 5px 10px rgba(0,0,0,.1)",
  backgroundColor: "rgb(255, 178, 56)",
  borderRadius: "6px",
  letterSpacing: "1.5px",
}

// Below is where the checkout component is defined.
// It has several functions and some default state variables.
const Checkout = class extends React.Component {
  state = {
    disabled: false,
    buttonText: "BUY NOW",
    paymentMessage: "",
  }

  resetButton() {
    this.setState({ disabled: false, buttonText: "BUY NOW" })
  }

  componentDidMount() {
    this.stripeHandler = window.StripeCheckout.configure({
      // You’ll need to add your own Stripe public key to the `checkout.js` file.
      // key: 'pk_test_STRIPE_PUBLISHABLE_KEY',
      key: "pk_test_testtesttesttesttesttest",
      closed: () => {
        this.resetButton()
      },
    })
  }

  openStripeCheckout(event) {
    event.preventDefault()
    this.setState({ disabled: true, buttonText: "WAITING..." })
    this.stripeHandler.open({
      name: "Demo Product",
      amount: amount,
      description: "A product well worth your time",
      token: token => {
        fetch(`AWS_LAMBDA_URL`, {
          method: "POST",
          mode: "no-cors",
          body: JSON.stringify({
            token,
            amount,
          }),
          headers: new Headers({
            "Content-Type": "application/json",
          }),
        })
          .then(res => {
            console.log("Transaction processed successfully")
            this.resetButton()
            this.setState({ paymentMessage: "Payment Successful!" })
            return res
          })
          .catch(error => {
            console.error("Error:", error)
            this.setState({ paymentMessage: "Payment Failed" })
          })
      },
    })
  }

  render() {
    return (
      <div style={cardStyles}>
        <h4>Spend your Money!</h4>
        <p>
          Use any email, 4242 4242 4242 4242 as the credit card number, any 3
          digit number, and any future date of expiration.
        </p>
        <button
          style={buttonStyles}
          onClick={event => this.openStripeCheckout(event)}
          disabled={this.state.disabled}
        >
          {this.state.buttonText}
        </button>
        {this.state.paymentMessage}
      </div>
    )
  }
}

export default Checkout
从“React”导入React
//向用户收取的硬编码金额(以美分为单位)
//您可以动态设置此变量以收取不同的金额
常数金额=2500
常量卡片样式={
显示:“flex”,
flexDirection:“列”,
为内容辩护:“周围的空间”,
alignItems:“灵活启动”,
填充:“3rem”,
boxShadow:“5px 5px 25px 0 rgba(46,61,73,2)”,
背景颜色:“fff”,
边界半径:“6px”,
最大宽度:“400px”,
}
常量按钮样式={
字体大小:“13px”,
textAlign:“居中”,
颜色:“fff”,
大纲:“无”,
填充:“12px 60px”,
盒形阴影:“2px 5px 10px rgba(0,0,0,1)”,
背景色:“rgb(255、178、56)”,
边界半径:“6px”,
字母间距:“1.5px”,
}
//下面是定义签出组件的地方。
//它有几个函数和一些默认状态变量。
const Checkout=类扩展了React.Component{
状态={
残疾人士:错,,
按钮文字:“立即购买”,
paymentMessage:“”,
}
重置按钮(){
this.setState({disabled:false,buttonText:“立即购买”})
}
componentDidMount(){
this.stripeHandler=window.StripeCheckout.configure({
//您需要将自己的条带公钥添加到`checkout.js`文件中。
//密钥:“pk\U测试\U条带\U可发布\U密钥”,
键:“pk_test_testtest”,
已关闭:()=>{
这个.resetButton()
},
})
}
openStripeCheckout(事件){
event.preventDefault()
this.setState({disabled:true,buttonText:“WAITING…”)
这个,脱衣舞娘,开门({
名称:“演示产品”,
金额:金额,,
描述:“值得您花费时间的产品”,
令牌:令牌=>{
获取(`AWS\u LAMBDA\u URL`{
方法:“张贴”,
模式:“无cors”,
正文:JSON.stringify({
代币
数量
}),
标题:新标题({
“内容类型”:“应用程序/json”,
}),
})
。然后(res=>{
console.log(“事务处理成功”)
这个.resetButton()
this.setState({paymentMessage:“支付成功!”})
返回res
})
.catch(错误=>{
console.error(“error:,error”)
this.setState({paymentMessage:“支付失败”})
})
},
})
}
render(){
返回(
花你的钱!

使用任何电子邮件4242作为信用卡号,任何3
数字,以及任何未来的到期日期。

this.openStripeCheckout(事件)} disabled={this.state.disabled} > {this.state.buttonText} {this.state.paymentMessage} ) } } 导出默认签出
pages/index.js

import React from "react"
import Helmet from "react-helmet"
import Favicon from "../components/fav-nma.png"
import Container from "../components/container"
import Layout from "../components/layout"
import Top from "../components/top"
//import Mainbody from "../components/mainbody"
import Apply from "../components/apply"
import Checkout from "../components/checkout"
import Price from "../components/price"
import Footer from "../components/footer"

const IndexPage = () => (
  <Layout>
    <Helmet link={[
      { rel: 'shortcut icon', type: 'image/png', href: `${Favicon}` }
  ]}>
      <meta property="og:type" content="website" />
      <meta property="og:url" content="test" />
      <meta property="og:title" content="test" />
      <meta property="og:description" content="test" />
      <meta property="og:image" content="test" />
      <meta property="fb:app_id" content="test" />
      <meta name="twitter:card" content="summary_large_image" />
      <meta name="twitter:title" content="test" />
      <meta name="twitter:description" content="test" />
      <meta name="twitter:image" content="test" />
    </Helmet>
    <Container>
      <Top />
      <Apply />
      <div>
        <Checkout />
      </div>
      <Price />
      <Footer />
    </Container>
  </Layout>
)

export default IndexPage
从“React”导入React
从“反应头盔”导入头盔
从“./components/fav nma.png”导入Favicon
从“./组件/容器”导入容器
从“./组件/布局”导入布局
从“./组件/顶部”导入顶部
//从“./组件/主体”导入主体
从“./组件/应用”导入应用
从“./组件/签出”导入签出
来自“./部件/价格”的进口价格
从“./组件/页脚”导入页脚
常量索引页=()=>(
)
导出默认索引扩展

错误
未捕获类型错误:无法读取未定义的属性“configure”
表示您没有加载
StripeCheckout

正如下面的教程所建议的,将条带签出脚本添加到文档中

<script src="https://checkout.stripe.com/checkout.js"></script>

您可以将其放在html文档的
中,或放在关闭
标记的正下方


此外,您还可以使用,它允许您在package.json中管理依赖项,并在代码中导入它


它的用法稍有不同,但它们的文档非常棒。

问题发生在生成过程中,因为“窗口”不是此代码段第2行中的有效对象:

componentDidMount() {
  this.stripeHandler = window.StripeCheckout.configure({
    key: "pk_test_testtesttesttesttesttest",
    closed: () => {
      this.resetButton()
    },
  })
}
盖茨比为您的站点构建静态资产时,“窗口”不存在。当您运行
Gatsby-service
gastby-build
或部署到Netlify(或任何地方)时,会发生这种情况

为了避免在构建过程中出现此问题,请将该行包装在if语句中,以检查
窗口是否存在

componentDidMount() {
  if (typeof window !== `undefined`) {
    this.stripeHandler = window.StripeCheckout.configure({
      key: `pk_test_testtesttesttesttesttest`,
      closed: () => {
        this.resetButton()
      }
    })
  }
}

我从以下地址窃取了此信息:

您能发布您的代码吗。。。404错误是一个页面未找到错误。可能是来自transpiring,或者是错误的文件路径…你能把你的代码发布到checkout.js使用的地方吗?嗨,Pari Baker,wsw。我在上面添加了代码。如果没有checkout.js,它过去是很好的,当我删除它时,它会返回到没有错误的状态。我打赌你告诉我的404可能会有文件路径问题,但我不知道确切的位置…嗨,赛斯。您的意思是将其添加到public/index.html或pages/index.js中吗?我两个都试过了,但两个都不起作用。它需要去你的
头部所在的任何地方,或者你关闭
html
标签的任何地方。它非常有效!我刚刚添加到public/index.html中,然后突然弹出。非常感谢你!顺便说一句,我检查了react stripe元素,但我还没有看到
componentDidMount() {
  if (typeof window !== `undefined`) {
    this.stripeHandler = window.StripeCheckout.configure({
      key: `pk_test_testtesttesttesttesttest`,
      closed: () => {
        this.resetButton()
      }
    })
  }
}