为什么 React hooks 可以有条件地使用并抛出错误?

joe*_* b. 7 reactjs eslint react-hooks

所以我们都知道我们不能像文档所说的那样将 React hooks 放在条件语句之后或之中。

function MyComponent(...) {
   if (condition) { 
      React.useState() // not allowed
   }
   return <div></div>;
}

function MyComponent(...) {
   if (condition) { 
      return null;
   }
   React.useState() // also not allowed
   return <div></div>;
}
Run Code Online (Sandbox Code Playgroud)

使用 React hooks 的 eslint 插件,我们会收到构建错误,指出上述内容是不允许的。

但为什么插件没有响应这个

function MyComponent(...) {
   if (errorCondition) { 
      throw Error;
   }
   React.useState() // allowed???
   return <div></div>;
}
Run Code Online (Sandbox Code Playgroud)

这是不允许的,并且插件没有更新来捕获这个吗?或者这实际上是允许的?文档似乎没有提到这一点

Dre*_*ese 0

我认为更重要的问题可能是为什么组件会决定抛出这样的错误,而不是发出副作用来指示发生了错误并简单地返回 null。

正如您所展示的,有条件的提前返回会禁止使用 React hook。

function MyComponent(...) {
  if (condition) { 
    return null;
  }
  React.useState() // not allowed
  return <div></div>;
}
Run Code Online (Sandbox Code Playgroud)

通过抛出错误,您将摆脱渲染的其余部分,因此之后是否可以调用 React hook 是一个有争议的问题。

function MyComponent(...) {
  if (errorCondition) { 
    throw Error;
  }
  React.useState() // allowed
  return <div></div>;
}
Run Code Online (Sandbox Code Playgroud)

考虑这个例子:

function MyComponent(...) {
  try {
    if (condition) { 
      throw Error;
    }
    React.useState() // not allowed
  } catch {
    // caught
  }
  return <div></div>;
}
Run Code Online (Sandbox Code Playgroud)

这也会产生来自 linter 的警告,因为您再次有条件地调用 React hook。

这是不允许的,并且插件没有更新来捕获这个吗?或者这实际上是允许的?

我不认为这是不允许的,但正如我上面所说,标记它似乎是不必要的,因为简单地抛出错误就会停止渲染组件的其余部分。我的猜测是,React 团队对此漠不关心,因为抛出这样的错误是极其罕见的,并希望某些父组件能够处理此异常,而不是仅在本地处理它并正常返回 null。

  • 我使用 React ErrorBoundary 组件来捕获抛出的错误并将其显示在屏幕上。所以它真的就像: &lt;ErrorBoundary&gt; &lt;MyComponent/&gt; // this throws error &lt;/ErrorBoundary&gt; 但无论如何,我们不会有条件地使用反应钩子,但我只是发现当我将 if-throw 向上移动以查看会发生什么时。 (2认同)