在我使用Next.js应用时,似乎无法访问window
:
未处理的拒绝(ReferenceError):window未定义
componentWillMount() {
console.log('window.innerHeight', window.innerHeight);
}
在我使用Next.js应用时,似乎无法访问window
:
未处理的拒绝(ReferenceError):window未定义
componentWillMount() {
console.log('window.innerHeight', window.innerHeight);
}
我需要从URL中访问哈希值,因此我想到了这个方法:
const hash = global.window && window.location.hash;
这是我使用的一个易于操作的解决方法。
const runOnClient = (func: () => any) => {
if (typeof window !== "undefined") {
if (window.document.readyState == "loading") {
window.addEventListener("load", func);
} else {
func();
}
}
};
使用方法:
runOnClient(() => {
// access window as you like
})
// or async
runOnClient(async () => {
// remember to catch errors that might be raised in promises, and use the `await` keyword wherever needed
})
这比仅仅检查typeof window !== "undefined"
要好,因为如果你只检查window是否未定义,它不会在页面被重定向时工作,它仅在加载一次期间工作。但是此解决方法即使页面被重定向到也能正常工作,而不仅仅是在加载一次期间工作。
window.onload
。 - 524F4ArunOnClient(f1); runOnClient(f2)
- OwnageIsMagic我将通用解决方案 (if (typeof window === 'undefined') return;
) 封装在一个自定义 hook 中,非常满意。它具有与 React 的 useMemo
hook 类似的接口,我非常喜欢。
import { useEffect, useMemo, useState } from "react";
const InitialState = Symbol("initial");
/**
*
* @param clientFactory Factory function similiar to `useMemo`. However, this function is only ever called on the client and will transform any returned promises into their resolved values.
* @param deps Factory function dependencies, just like in `useMemo`.
* @param serverFactory Factory function that may be called server side. Unlike the `clientFactory` function a resulting `Promise` will not be resolved, and will continue to be returned while the `clientFactory` is pending.
*/
export function useClientSideMemo<T = any, K = T>(
clientFactory: () => T | Promise<T>,
deps: Parameters<typeof useMemo>["1"],
serverFactory?: () => K
) {
const [memoized, setMemoized] = useState<T | typeof InitialState>(
InitialState
);
useEffect(() => {
(async () => {
setMemoized(await clientFactory());
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
return typeof window === "undefined" || memoized === InitialState
? serverFactory?.()
: memoized;
}
使用示例:
我正在使用它来动态导入在next.js中与SSR不兼容的库,因为其自身的动态导入仅与组件兼容。
const renderer = useClientSideMemo(
async () =>
(await import("@/components/table/renderers/HighlightTextRenderer"))
.HighlightTextRendererAlias,
[],
() => "text"
);
正如您所看到的,我甚至实现了一个回退工厂回调,因此您可以在最初在服务器上呈现时提供结果。在所有其他方面,这个钩子应该表现得类似于React的useMemo
钩子。欢迎反馈。
当我刷新页面时(由于导入与SSR不兼容),我遇到了同样的问题。
对我有用的解决方法是进入出现此问题的页面并强制将导入设置为动态:
import dynamic from 'next/dynamic';
const SomeComponent = dynamic(()=>{return import('../Components/SomeComponent')}, {ssr: false});
//import SomeComponent from '../Components/SomeComponent'
在我开发next.js网站应用时,我遇到了同样的问题。 解决方法是,在生命周期方法或React Hook中引用window对象。例如,假设我想使用Redux创建存储变量,并在其中使用window对象,可以按照以下方式进行:
let store
useEffect(()=>{
store = createStore(rootReducers, window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__())
}, [])
....
基本上,当您使用Windows对象时,总是使用钩子或componentDidMount()
生命周期方法
以下是一个代码片段,展示了如何在 localStorage
中创建、更新(也可以使用 create 函数进行更新)和删除一个键(这里是 username
)
const [username, setUsername] = useState<null | string>(null);
useEffect(() => {
if (typeof window !== "undefined" && window.localStorage) {
let token = localStorage.getItem("username");
setUsername(token);
}
}, [setUsername]);
const createItem = (newUsername: string) => {
if (typeof window !== "undefined" && window.localStorage) {
localStorage.setItem("username", newUsername);
let token = localStorage.getItem("username");
setUsername(token);
}
};
const removeItem = () => {
if (typeof window !== "undefined" && window.localStorage) {
localStorage.removeItem("username");
setUsername(null);
}
};
console.log(username, "username");
import { useRouter } from "next/router";
const navigator = useRouter()
console.log(navigator.pathname);
日期:2021年6月8日
检查窗口对象是否存在,然后跟随其中的代码。
function getSelectedAddress() {
if (typeof window === 'undefined') return;
// Some other logic
}
componentDidMount()
中,该方法仅在客户端执行,因此可以使用window
。此外,componentWillMount()
在v17中已被弃用。https://github.com/zeit/next.js/wiki/FAQ#i-use-a-library-which-throws-window-is-undefined - Alexander Staroselsky