【问题标题】:Adyencheckout is not a constructor - NextJSAdyencheckout 不是构造函数 - NextJS
【发布时间】:2021-05-30 20:53:39
【问题描述】:

我正在尝试使用 NextJS 实现 Adyen dropin 支付 UI,但我在初始化 Adyen dropin 组件时遇到了问题。

我需要动态导入 Adyen web,否则我收到错误 window is not defined 但是,在阅读 NextJS 文档后,动态导入会创建一个组件,但我不知道如何用作构造函数。

我尝试了下面的代码,但收到错误 TypeError: AdyenCheckout is not a constructor

我是 NextJS 的新手,不知道应该如何导入和初始化 Adyen。

谁能指出我正确的方向?

import Head from 'next/head';
import { useRef, useEffect, useState } from 'react';
import {callServer, handleSubmission} from '../util/serverHelpers';
//dynamic import below. Imports as a component 
//import dynamic from 'next/dynamic';
//const AdyenCheckout = dynamic(() => import('@adyen/adyen-web'), {ssr: false});
import '@adyen/adyen-web/dist/adyen.css';

export default function Dropin(){

  const dropinContainer = useRef(null);
  const [paymentMethods, setPaymentMethods] = useState();
  //const [dropinHolder, setDropinHolder] = useState();

  //Get payment methods after page render
  useEffect( async () => {
    const response = await callServer(`${process.env.BASE_URL}/api/getPaymentMethods`);
    setPaymentMethods(prev => prev = response);
  },[]);
   
  //Adyen config object to be passed to AdyenCheckout
  const configuration = {
    paymentMethodsResponse: paymentMethods,
    clientKey: process.env.CLIENT_KEY,
    locale: "en_AU",
    environment: "test",
    paymentMethodsConfiguration: {
      card: {
        showPayButton: true,
        hasHolderName: true,
        holderNameRequired: true,
        name: "Credit or debit card",
        amount: {
          value: 2000,
          currency: "AUD"
        }
      }
    },
    onSubmit: (state, component) => {
      if (state.isValid) {
        handleSubmission(state, component, "/api/initiatePayment");
      }
    },
    onAdditionalDetails: (state, component) => {
      handleSubmission(state, component, "/api/submitAdditionalDetails");
    },
  };

  //const checkout = new AdyenCheckout(configuration);
  const AdyenCheckout = import('@adyen/adyen-web').default;
  const adyenCheckout = new AdyenCheckout(configuration);
  const dropin = adyenCheckout.create('dropin').mount(dropinContainer.current);

  return (
      <div>
        <Head>
        <title>Dropin</title>
        
        </Head>
        <div ref={dropin}></div>
      </div>
  )
}

【问题讨论】:

  • 您是否在页面顶部的 CSS 导入上方尝试了一个简单明了的import AdyenCheckout from '@adyen/adyen-web';
  • 是的,我应该提到这一点。当我使用标准导入时,我只收到window is not defined 错误。
  • 动态 import 返回一个承诺,你需要 await 来获得它。我还建议将其移动到 useEffect 内,因为它的代码似乎依赖于 window 的存在。
  • 另外,在使用next/dynamic:Why am I getting ReferenceError: self is not defined in Next.js when I try to import a client-side library时,这是否有助于回答您的问题?
  • 所以我将所有内容都移到了useEffect 中,并将导入放在async 函数中,但仍然出现AdyenCheckout is not a contructor 错误。 @juliomalves 我最初认为动态导入可以解决我的问题,但似乎动态导入返回的是可加载组件而不是实际模块

标签: javascript reactjs next.js adyen


【解决方案1】:

我能够通过使用嵌套在useEffect 函数中的async 函数中的default 值导入模块来解决此问题。

import Head from 'next/head';
import { useRef, useEffect, useState } from 'react';
import {callServer, handleSubmission} from '../util/serverHelpers'; 
import '@adyen/adyen-web/dist/adyen.css';

export default function Dropin(){

  const dropinContainer = useRef();
  const [paymentMethods, setPaymentMethods] = useState({});

  useEffect(() => {
    const init = async () => {
      const response = await callServer(`${process.env.BASE_URL}/api/getPaymentMethods`)
      .then(setPaymentMethods(response));

      console.log(paymentMethods);

      const configuration = {
        paymentMethodsResponse: paymentMethods,
        clientKey: process.env.CLIENT_KEY,
        locale: "en_AU",
        environment: "test",
        paymentMethodsConfiguration: {
          card: {
            showPayButton: true,
            hasHolderName: true,
            holderNameRequired: true,
            name: "Credit or debit card",
            amount: {
              value: 2000,
              currency: "AUD"
            }
          }
        },
        onSubmit: (state, component) => {
          if (state.isValid) {
            handleSubmission(state, component, "/api/initiatePayment");
          }
        },
        onAdditionalDetails: (state, component) => {
          handleSubmission(state, component, "/api/submitAdditionalDetails");
        },
      };

      console.log(configuration.paymentMethodsResponse);
      const AdyenCheckout = (await import('@adyen/adyen-web')).default;
      const checkout = new AdyenCheckout(configuration);
      checkout.create('dropin').mount(dropinContainer.current);
    }
    init();
  },[]);

  return (
      <div>
        <Head>
        <title>Dropin</title>
        </Head>
        <div ref={dropinContainer}></div>
      </div>
  )
}

【讨论】:

  • 有趣,通过这样做,我这边有一些改进,它解决了原来的问题。但是我不明白为什么,你能解释一下为什么会这样吗?同样在我的情况下(使用 Vue JS),它看起来好像我导入了两次库,但不确定这是最好的方法,特别是考虑到它的大小。
猜你喜欢
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 2013-12-25
  • 2021-01-11
  • 2015-12-04
  • 2018-11-29
  • 2016-12-04
  • 2020-12-27
相关资源
最近更新 更多