Next.js:文档未定义

Lou*_*ost 27 node.js reactjs next.js

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

文档未定义

我正在使用 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
Run Code Online (Sandbox Code Playgroud)

Par*_*tho 40

例如,当模块包含仅在浏览器中工作的库时。有时动态导入可以解决这个问题。

看一下下面的例子:

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home
Run Code Online (Sandbox Code Playgroud)


小智 29

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

  • 使用 INSIDE useEffect 文档对我有用。 (2认同)

Ali*_*Ali 27

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

if (typeof window !== "undefined") {
Run Code Online (Sandbox Code Playgroud)

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

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

import {router} from "next/client";
Run Code Online (Sandbox Code Playgroud)


Dar*_*ert 17

您需要包装您的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 = () => {

        };
    }
};
Run Code Online (Sandbox Code Playgroud)

  • 请注意,“process.browser”已被弃用。您现在应该使用`typeof window === 'undefined'`。参考https://github.com/zeit/next.js/issues/5354#issuecomment-520305040 (6认同)
  • 有人知道为什么即使我们输入“使用客户端”也会发生这种情况吗? (3认同)

小智 7

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

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


Mai*_*ton 6

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

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

React.useEffect(() => {
    set_document(document)
}, [])
Run Code Online (Sandbox Code Playgroud)

  • 但这仅限于组件吗?这不是文档,而是声明此 useState 挂钩的组件中的一段状态。 (3认同)