我正在使用 Next.js 构建一个开源博客平台,但在部署过程中遇到了令人沮丧的错误。当尝试预渲染 /write 页面时,我收到以下错误:
ReferenceError: document is not defined
at Object.<anonymous> (/vercel/path0/.next/server/chunks/34.js:10601:12)
我尝试了各种解决方案,例如检查服务器端代码中的 DOM 访问并使用条件语句包装此类代码,但错误仍然存在。
附加信息:
Next.js 版本:19.4.13 项目存储库:https://github.com/MuhammadKaifNazeer/blogvarse/tree/main
这是./write/page.jsx的代码
"use client";
import Image from "next/image";
import styles from "./writePage.module.css";
import { useEffect, useState } from "react";
import "react-quill/dist/quill.bubble.css";
import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
import {
getStorage,
ref,
uploadBytesResumable,
getDownloadURL,
} from "firebase/storage";
import { app } from "@/utils/firebase";
import ReactQuill from "react-quill";
const WritePage = () => {
const { status } = useSession();
const router = useRouter();
const [open, setOpen] = useState(false);
const [file, setFile] = useState(null);
const [media, setMedia] = useState("");
const [value, setValue] = useState("");
const [title, setTitle] = useState("");
const [catSlug, setCatSlug] = useState("");
useEffect(() => {
const storage = getStorage(app);
const upload = () => {
const name = new Date().getTime() + file.name;
const storageRef = ref(storage, name);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is " + progress + "% done");
switch (snapshot.state) {
case "paused":
console.log("Upload is paused");
break;
case "running":
console.log("Upload is running");
break;
}
},
(error) => {},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setMedia(downloadURL);
});
}
);
};
file && upload();
}, [file]);
if (status === "loading") {
return <div className={styles.loading}>Loading...</div>;
}
if (status === "unauthenticated") {
router.push("/");
}
const slugify = (str) =>
str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "")
.replace(/[\s_-]+/g, "-")
.replace(/^-+|-+$/g, "");
const handleSubmit = async () => {
const res = await fetch("/api/posts", {
method: "POST",
body: JSON.stringify({
title,
desc: value,
img: media,
slug: slugify(title),
catSlug: catSlug || "style",
}),
});
if (res.status === 200) {
const data = await res.json();
router.push(`/posts/${data.slug}`);
}
};
return (
<div className={styles.container}>
<input
type="text"
placeholder="Title"
className={styles.input}
onChange={(e) => setTitle(e.target.value)}
/>
<select className={styles.select} onChange={(e) => setCatSlug(e.target.value)}>
<option value="style">style</option>
<option value="fashion">fashion</option>
<option value="food">food</option>
<option value="culture">culture</option>
<option value="travel">travel</option>
<option value="coding">coding</option>
</select>
<div className={styles.editor}>
<button className={styles.button} onClick={() => setOpen(!open)}>
<Image src="/plus.png" alt="" width={16} height={16} />
</button>
{open && (
<div className={styles.add}>
<input
type="file"
id="image"
onChange={(e) => setFile(e.target.files[0])}
style={{ display: "none" }}
/>
<button className={styles.addButton}>
<label htmlFor="image">
<Image src="/image.png" alt="" width={16} height={16} />
</label>
</button>
<button className={styles.addButton}>
<Image src="/external.png" alt="" width={16} height={16} />
</button>
<button className={styles.addButton}>
<Image src="/video.png" alt="" width={16} height={16} />
</button>
</div>
)}
<ReactQuill
className={styles.textArea}
theme="bubble"
value={value}
onChange={setValue}
placeholder="Tell your story..."
/>
</div>
<button className={styles.publish} onClick={handleSubmit}>
Publish
</button>
</div>
);
};
export default WritePage;
我尝试过的:
我的期望:
我预计 /write 页面会成功预渲染,不会出现任何错误。我希望页面能够在服务器端和客户端上正确加载并按预期运行。
问题:
ReferenceError:文档未定义
可能的原因:
从“react-quill”导入ReactQuill;
解决方案:
有些库不支持 NextJS,因此必须动态导入。
尝试改变:
import ReactQuill from "react-quill";
到
import dynamic from 'next/dynamic';
const ReactQuill = dynamic(() => import("react-quill"),
{
loading: () => <p>Editor Loading...</p>,
ssr: false
}
);
请阅读: