React: eslint-plugin-react-hooks:外部条件发生“钩被有条件地调用”错误

创建于 2019-09-19  ·  4评论  ·  资料来源: facebook/react

您是否要请求功能或报告错误

错误(可能)

目前的行为是什么?

插件显示此错误:

React Hook的“ useState”被有条件地调用。 在每个组件渲染中,必须以完全相同的顺序调用React Hook。 提早归还后,您是否不小心打了个React Hook? (反应挂钩/挂钩规则)

但是我不认为我有条件地打电话给任何钩子。

代码:

https://codesandbox.io/s/exciting-bhabha-mqj7q

function App(props) {
  const someObject = { propA: true, propB: false };

  for (const propName in someObject) {
    if (propName === true) {
      console.log("something");
    } else {
      console.log("whatever");
    }
  }

  // THE PLUGIN ERROR MSG ON THIS useState
  const [myState, setMyState] = useState(null);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

image

预期的行为是什么?

在这种情况下,该插件不会显示错误。

哪个版本的React,以及哪个浏览器/操作系统受此问题影响?

image

ESLint Rules Bug

最有用的评论

所有4条评论

我注意到对于这个特定的例子:

pathsFromStartToEnd3
allPathsFromStartToEnd2

possiblyHasEarlyReturn也是true


pathsFromStartToEndallPathsFromStartToEnd不相等时,将报告此特定错误。

参见RulesOfHooks.js第404行


如果将for..in循环内的代码抽象到一个单独的函数中,则lint错误将消失。

在这种情况下, pathsFromStartToEndallPathsFromStartToEnd都等于2

  const someObject = { propA: true, propB: false };
  const someFunction = (propName) => {
    if (propName === true) {
      console.log("something");
    } else {
      console.log("whatever");
    }
  }
  for (const propName in someObject) {
    someFunction(propName)
  }
  const [myState, setMyState] = useState(null);

我仍然不确定为什么。

@gaearon ,我创建了一个MR来解决并解决此问题(#16853)。

发生这种情况的主要原因是allPathsFromStartToEnd值计算错误。
在此示例中,从起点到终点的路径数应为3,但函数返回2。

发生这种情况的原因是由于循环路径的缓存存在缺陷。 因此,在普通图遍历中,我们也需要路径历史记录,但是它只需要一个循环元素列表,而导致该路径的元素是未知的。
结果,当在for...in obj使用条件时,根据方向,我们可能会丢失一些路径。

对于2.4.0来说,这仍然是一个问题,简单一点的复制:

import * as React from "react";

function Component() {
  let isLastEven = false;
  for (let x of [1, 2, 3]) {
    if (x % 2 == 0) {
      isLastEven = true;
    } else {
      isLastEven = false;
    }
  }
  let y = React.useMemo(() => 1, []);
  return <div>{y}</div>;
}

#16853是否可以重新打开?

此页面是否有帮助?
0 / 5 - 0 等级