Invalid hook call

191 阅读1分钟

相信用过 React hooks 的同学对下面这个问题并不陌生

# Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app See for tips about how to debug and fix this problem.

26AC6F26-3C07-4707-977E-04DE12E43FFE.png

这个错误提示已经足够清楚。

首先检查 React 版本是否支持 Hooks,需要 16.8 以上版本。

其次是看一下代码是否符合 hooks 规则,由于 hooks 是顶层函数,当我们将其用到非顶级作用域时会出 Invalid hook call 的错误。

import { useState } from "react";

export const Demo = () => {
  // 正确用法
  const [count, setConut] = useState(0);

  // 错误用法
  // const errorFunction = () => {
  //   const [name, setName] = useState("kn");
  // };

  return (
    <div>
      <span>{count}</span>
      <button
        onClick={() => {
          setConut(count + 1);
        }}
      >
        +1
      </button>
    </div>
  );
};

如果以上都没问题,那我猜你可能踩坑了,那就是第三种情况。

例如我们有 2 个独立包 A 和 B,A 包依赖 B 包,且两者都依赖 React,为了方便调试,我们使用了 link 功能。

在 B 包根目录执行 npm link

在 A 包根目录执行 npm link B

当我们在 A 包启动项目时就很可能出现 Invalid hook call ,原因是在这种情况下,你的打包器可能会检测到 2 个 React,一个在 A 包中,一个在 B 包中,解决办法是 A 包使用 B 包的 React。

假如两者在同一目录,我们在 A 目录执行 npm link ../B/node_modules/react,这样就能保证使用相同的 React,从而解决问题。

一些等价 link 的方案也可能出现类型问题,解决思路相同。