作者:愿今夜不再孤单 | 来源:互联网 | 2023-09-14 13:03
引言
这个问题与Next.js的服务器端渲染有关。Next.js默认会尝试为您的网站使用SSR。这意味着,由于我们是在服务器上而不是在浏览器中,所以 "窗口 "对象并不存在。解决这个问题的方法是强迫Next.js在浏览器中运行你的代码,我将解释如何做到这一点。
使用useEffect钩子
该useEffect钩子总是在浏览器中运行,所以我们可以用它来确保我们的代码只能从那里运行。关于钩子的快速入门知识,请查看这篇文章。
下面是一个简单应用的示例代码,它将用户最后一次访问网站的时间存储在本地存储中。如果你不熟悉在React或Next.js中使用localStorage,可以看看我们这里的这个教程,它使用了类似的方法。这个方法是相同的,但有一个小的区别,那就是你可以在vanilla React组件的主体中使用localStorage,因为默认没有SSR:
function updateLastSeen() {
const lastSeen = window.localStorage.getItem("last-seen") ?? new Date();
window.localStorage.setItem("last-seen", new Date().toString());
return lastSeen;
}
function WindowPage() {
const lastSeen = updateLastSeen();
return Last Seen: {lastSeen}
;
}
运行这个,我们得到这个你可能熟悉的错误:
![](https://img1.php1.cn/3cd4a/24de0/4aa/2f29d29af1762c3e.png)
为了解决这个问题,让我们引入一个自定义的钩子,它涉及一个 useEffect。
function useLastSeen() {
const [lastSeen, setLastSeen] = useState(null);
const retrieved = useRef(false); //To get around strict mode running the hook twice
useEffect(() => {
if (retrieved.current) return;
retrieved.current = true;
setLastSeen(updateLastSeen());
}, []);
return lastSeen;
}
我已经把我们的逻辑移到了一个自定义的钩子上,只是为了保持代码的简洁。现在随着我们代码的改变,代码将只在钩子运行时运行,也就是在客户端。
然后我们可以将我们的组件更新为。
function WindowPage() {
const lastSeen = useLastSeen();
return (
Last Seen: {lastSeen}
);
}
这段代码更简洁,而且由于 useEffect里面的钩子只在客户端运行,我们的错误就消失了
检查窗口是否被定义
另一种方法是在我们运行代码之前简单地检查窗口对象是否被定义。如果代码在服务器上运行,由于我们不在浏览器中,窗口对象就不存在。
我们不能使用与之前相同的例子,因为这种方法有一个关键的区别。因为我们没有等待组件的渲染,任何对页面HTML的差异都会导致服务器端渲染的页面版本与客户端不同,我们会在Next.js中得到一个错误。
在这个例子中,我们将为窗口对象添加一个事件监听器,以跟踪页面上的点击和它们的位置。
const isBrowser = () => typeof window !== "undefined"; //The approach recommended by Next.js
function WindowPage() {
const [lastClick, setLastClick] = useState("");
if (isBrowser()) { //Only add the event listener client-side
window.addEventListener("click", (e) =>
setLastClick(`${e.pageX}, ${e.pageY}`)
);
}
return (
Click at: {lastClick}
);
}
![](https://img1.php1.cn/3cd4a/24de0/4aa/923e1d4c8ad87063.png)
正如我们所看到的,代码并没有在服务器上运行,所以Next.js现在很高兴了
希望这两种方法中的一种能帮助解决你的问题。我推荐第一种方法,因为它涵盖了大多数情况,而且你不必处理Next.js发现渲染不匹配的可能性。
以上就是修复Next.js中window is not defined方法详解的详细内容,更多关于Next.js window is not defined的资料请关注编程笔记其它相关文章!