You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中Window和document未定义:此前正常运行后失效

解决Next.js中document未定义导致的视差效果故障

问题原因

Next.js默认采用服务端渲染(SSR),组件初始化逻辑会在服务端环境执行,而服务端没有浏览器的document对象。你通过useMemo直接获取:root元素的代码会在服务端运行,因此抛出document is not defined错误。

解决方案

将DOM相关的获取操作移至useEffect钩子中——useEffect仅在客户端渲染完成后执行,此时document对象已存在。同时优化视差处理逻辑,确保仅在客户端环境下执行DOM操作。

修改后的代码

Index.js

import Image from "next/image";
import Link from "next/link";
import { useState, useEffect } from "react";
import { FaDiscord } from "react-icons/fa";

export default function Home() {
  const [isVisible, setIsVisible] = useState(true);
  const [root, setRoot] = useState(null);

  useEffect(() => {
    // 客户端环境下获取root元素
    setRoot(document.querySelector(":root"));
    
    // 滚动监听逻辑
    const listenToScroll = () => {
      const heightToHideFrom = 150;
      const winScroll = document.body.scrollTop || document.documentElement.scrollTop;

      if (winScroll > heightToHideFrom) {
        isVisible && setIsVisible(false);
      } else {
        setIsVisible(true);
      }
    };

    window.addEventListener("scroll", listenToScroll);
    return () => window.removeEventListener("scroll", listenToScroll);
  }, [isVisible]);

  const parallaxHandler = (e) => {
    if (!root) return; // 确保root存在再执行
    const x = (e.clientX - window.innerWidth / 2) / 100;
    const y = (e.clientY - window.innerHeight / 2) / 100;
    root.style.setProperty("--posX", -x);
    root.style.setProperty("--posY", -y);
  };

  return (
    <>
      {/* HERO */}
      <section
        onMouseMove={parallaxHandler}
        className="w-[100vw] bg-[url(/Home/wave.svg)] bg-orange bg-contain bg-bottom bg-no-repeat parallax h-[100vh] pt-24 lg:px-0 px-4 lg:pt-0 lg:flex lg:text-left text-center justify-center align-middle"
      >
        <div className="self-center xl:mb-20 px-0 lg:px-20">
          <h1 className="font-title sm:text-8xl text-5xl">
            Text
            <br /> <span className="text-black"> Audio </span>
          </h1>
          <h2 className="font-poppins sm:text-2xl text-center lg:text-left text-xl uppercase py-4">
            With crypto and fiat, coming soon...
          </h2>
          <Link href="https://discord.com/invite/" passHref>
            <a target="_blank">
              <button className="flex rounded gap-2 text-md align-middle lg:mx-0 mx-auto bg-grey p-4">
                <FaDiscord size="2em" color="#FB713A " className="cursor-pointer" />
                <p className="my-auto text-orange"> Join our Discord </p>
              </button>
            </a>
          </Link>
        </div>
        <div className="relative max-h-[60%] lg:max-h-[100%] w-[471px] h-[549px] lg:w-[753px] lg:h-[878px] inline-block justify-center xl:flex-col sm:h-[586px] sm:w-[502px] width object-center">
          <Image
            alt="app_bg"
            className="app_bg"
            src="/Home/hero_app.png"
            quality={100}
            layout="fill"
            objectFit="contain"
            priority
          />
        </div>
        {isVisible && (
          <Link href="#whatis">
            <div className="cursor-pointer text-center absolute bottom-0 p-0 left-[40%] right-[40%]">
              <div className="scroll__down">
                <span className="scroll__mouse">
                  <span className="scroll__wheel"></span>
                </span>
              </div>
              <p className="text-orange text-xs font-semibold animate-pulse">
                SCROLL TO EXPLORE{" "}
              </p>
            </div>
          </Link>
        )}
      </section>
    </>
  );
}

Styles.css(无需修改)

:root {
  --posX: 0;
  --posY: 0;
}

.parallax .app_bg {
  transform: translate(calc(var(--posX) * 1px), calc(var(--posY) * 1px));
}

额外说明

  • 把listenToScroll函数移到useEffect内部,避免依赖外部变量导致的不必要重渲染,同时确保仅在客户端执行。
  • 在parallaxHandler中添加root存在性判断,防止客户端初始化完成前触发事件导致的错误。

内容的提问来源于stack exchange,提问作者Demetris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:43:57