Adyencheckout 不是构造函数 - NextJS

时间:2021-03-01 10:23:16

标签: javascript reactjs next.js adyen

我正在尝试使用 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>
  )
}

1 个答案:

答案 0 :(得分:2)

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

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>
  )
}