Next.js:文档未定义

IT技术 node.js reactjs next.js
2021-03-26 09:30:55

我正在尝试创建一个人们可以付款的付款表格,但我不断收到此错误。

文档未定义

我正在使用 Next.js。请看我下面的代码:

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
6个回答

我认为,在服务器渲染模式下,文档是未定义的。您应该能够在类生命周期方法或 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

您需要包装您的documentusing validator process.browser,因为该文档属于客户端,并且在服务器端渲染 nextjs 时发生错误。

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

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

        };
    }
};
请注意,process.browser已被弃用。您现在应该使用typeof window === 'undefined'. 参考github.com/zeit/next.js/issues/5354#issuecomment-520305040
2021-05-23 09:30:55

要访问 Next.js 中的文档,您需要先等待页面渲染,然后将其放入变量中,如下所示:

const [_document, set_document] = React.useState(null)

React.useEffect(() => {
    set_document(document)
}, [])
正是我所需要的。非常感谢!
2021-06-09 09:30:55

对我来说,这个错误是由很多错误引起的:首先,你必须使用

if (typeof window !== "undefined") {

对于每个window.document.尤其是对于localStorage.函数(我自己忘记对 localStorage.getItem 使用这个 if 子句并且错误没有修复)

另一个问题是下面一行的导入是完全错误的!:

import {router} from "next/client";

您应该阅读 node.js 中的 JS 和浏览器中的 JS 之间的区别。在 node.js 中,您没有 DOM API(窗口、文档、document.getElementById 等),只有当您的 HTML 在称为浏览器窗口的事物中呈现时才能拥有。所以 next.js 使用 node.js 来运行 JS 代码并获取结果来渲染 HTML 文件。但是在 node.js 中,没有什么是浏览器的窗口。

我的英语很差。但我希望这个答案对你有帮助。