node.jsreactjsnext.js

Next.js: document is not defined


I am trying to create a payment form where people can pay but I keep getting this error.

document is not defined

I'm using Next.js. Please see my code below:

import React from "react";
import {Elements, StripeProvider} from 'react-stripe-elements';
import CheckoutForm from '../../components/Payment/CheckoutForm';
import { useRouter } from 'next/router';


var stripe_load = () => {
    var aScript = document.createElement('script');
    aScript.type = 'text/javascript';
    aScript.src = " https://js.stripe.com/v3/";

    document.head.appendChild(aScript);
    aScript.onload = () => {

    };
};

function Payment({host}) {
    const key = host.includes('localhost') ? 'test' : 't';

    stripe_load();

    const router = useRouter();

    return (
        <div className="Payment Main">
            <StripeProvider apiKey={key}>
                <Elements>
                    <CheckoutForm planid={router.query.id}/>
                </Elements>
            </StripeProvider>
            <br/>
            <br/>
            <p>Powered by Stripe</p>
        </div>
    );
};


Payment.getInitialProps = async ctx => {
    return { host: ctx.req.headers.host }
};

export default Payment

Solution

  • I think, in server rendering mode, the document is undefined. You should be able to use it inside class lifecycle methods or useEffect

    import React, {useEffect} from "react";
    import {Elements, StripeProvider} from 'react-stripe-elements';
    import CheckoutForm from '../../components/Payment/CheckoutForm';
    import { useRouter } from 'next/router';
    
    
    var stripe_load = () => {
        var aScript = document.createElement('script');
        aScript.type = 'text/javascript';
        aScript.src = " https://js.stripe.com/v3/";
    
        document.head.appendChild(aScript);
        aScript.onload = () => {
    
        };
    };
    
    function Payment({host}) {
        const key = host.includes('localhost') ? 'test' : 't';
    
        useEffect(() => {
          var aScript = document.createElement('script');
           aScript.type = 'text/javascript';
           aScript.src = " https://js.stripe.com/v3/";
    
           document.head.appendChild(aScript);
           aScript.onload = () => {
    
           };
        }, [])
        //stripe_load();
    
        const router = useRouter();
    
        return (
            <div className="Payment Main">
                <StripeProvider apiKey={key}>
                    <Elements>
                        <CheckoutForm planid={router.query.id}/>
                    </Elements>
                </StripeProvider>
                <br/>
                <br/>
                <p>Powered by Stripe</p>
            </div>
        );
    };
    
    
    Payment.getInitialProps = async ctx => {
        return { host: ctx.req.headers.host }
    };
    
    export default Payment