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

时间:2021-02-28 18:05:57

标签: javascript reactjs typescript react-hooks next.js

ReferenceError: window is not defined

当 NextJS 尝试渲染页面时,此错误会在服务器端引发。但是您可以在 window 钩子中使用 useEffect,如 here 一样。

我的问题是如何创建自定义挂钩。我尝试过类似的事情:

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);
    });
};

此处的 window 用于 useEffect。但是我得到了错误,因为当我打电话

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

NextJS 无法识别。

我该如何处理?

2 个答案:

答案 0 :(得分:0)

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

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

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 以简化用法和语法。

答案 1 :(得分:0)

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