开发者问题收集

NextJS:如何在自定义钩子中使用窗口?

2021-02-28
10833

ReferenceError:window 未定义

当 NextJS 尝试呈现页面时,此错误会在服务器端引发。但您可以在 useEffect 钩子中使用 window ,如 此处 所述。

我的问题是如何创建自定义钩子。我尝试过类似这样的操作:

export const useEventListener = (
    target: EventTarget, event: string, listener: EventListenerOrEventListenerObject, trigger = true,
): void => {
    useEffect(() => {
        target.addEventListener(event, listener);
        trigger && target.dispatchEvent(new Event(event));
        return () => target.removeEventListener(event, listener);
    });
};

此处的 windowuseEffect 中使用。但我收到错误,因为当我调用

useEventListener(window, 'scroll', () => {...});

NextJS 无法识别它。

我该如何处理?

2个回答

我不确定该解决方案是否是最好的,但您可以使用 globalThis 代替 window ,它等同于客户端上的 window

Yoskutik
2021-03-01

您仍会收到相同的错误,因为当您调用 useEventListener(window, 'scroll', () => {...}); 时,服务器上仍未定义 window 。您应仅在 useEffect 的回调中引用 window

例如,如果未定义 target ,则可以将现有的自定义钩子修改为默认为 window

export const useEventListener = (
    target: EventTarget, 
    event: string, 
    listener: EventListenerOrEventListenerObject, 
    trigger = true
): void => {
    useEffect(() => {
        const t = target || window
        t.addEventListener(event, listener);
        trigger && t.dispatchEvent(new Event(event));
        return () => t.removeEventListener(event, listener);
    });
};

然后,您可以像这样调用钩子:

useEventListener(undefined, 'scroll', () => {...});

您甚至可以从钩子中删除 target 参数,并始终使用 window ,以简化用法和语法。

juliomalves
2021-02-28