在 Next JS 中有条件地使用 React hooks

Using React hooks conditionally in Next JS

编辑:这个问题最初是关于在 CodeSandbox 环境中使用 React 挂钩时的类型错误,但我已经对其进行了更新,以便它对未来的访问者有用。

我正在使用以下代码尝试创建一个挂钩,以使用滚动位置来设置网站高度的动画 header。问题是我已经尝试了各种方法来阻止它在服务器上出错但不断收到各种错误(尽管检查 window object 是否存在)。

我原来的问题中有一些示例代码,我已经更新了以下代码沙箱。

https://codesandbox.io/s/p5y6262qzm

原始问题:

未处理的拒绝(类型错误):Object(…) 不是函数

首先,我知道这个标题还有其他问题,但似乎有多种原因,我找不到涵盖我的特殊情况的答案。

我可以用来生成示例的最简单(不完整)的代码是...

import React, { useState, useEffect } from "react";

const useScrollPosition = () => {
  // Store the state
  const [scrollPos, setScrollPos] = useState(window.pageYOffset);

  return scrollPos;
};

export default useScrollPosition;

虽然在这个codesandbox中有一个更完整的例子来说明我想做什么:

https://codesandbox.io/s/p5y6262qzm

我猜这很简单,我似乎无法理解它。

此 Next.js 设置导致

TypeError: window.addEventListener is not a function

客户端错误,因为 window 全局变量被局部变量覆盖:

const window = window || {
  width: 0,
  height: 0,
  pageXOffset: 0,
  pageYOffset: 0
};

应该是:

const w = (typeof window !== 'undefined' && window) || {
  width: 0,
  height: 0,
  pageXOffset: 0,
  pageYOffset: 0
};

这将导致在服务器端呈现期间使用模拟对象,并在客户端呈现期间使用 window

更好的解决方案是避免使用特定于客户端的组件,例如react-no-ssr。由于有条件地应用钩子(useScrollPosition钩子)不是一个好的做法,所以它是一个使用这个钩子的组件需要有条件地渲染。