javascript - 你能用 React hooks 提前回来吗?

标签 javascript reactjs react-hooks

React 文档清楚地表明 calling hooks conditionally will not work . From the original React hooks presentation ,原因是 React 使用你调用钩子(Hook)的顺序来注入(inject)正确的值。

我理解这一点,但现在我的问题是从带有钩子(Hook)的函数组件中提前返回是否可以。

那么这样的事情是允许的吗?:

import React from 'react';
import { useRouteMatch, Redirect } from 'react-router';
import { useSelector } from 'react-redux';

export default function Component() {
  const { match } = useRouteMatch({ path: '/:some/:thing' });
  if (!match) return <Redirect to="/" />;

  const { some, thing } = match.params;
  const state = useSelector(stateSelector(some, thing));

  return <Blah {...state} />;
}

从技术上讲,useSelector Hook 是有条件地调用的,但是调用它们的顺序在渲染之间不会改变(即使可能会少调用一个 Hook )。

如果不允许这样做,您能否解释为什么不允许这样做,并提供在带钩子(Hook)的函数组件中提前返回的一般替代方法?

最佳答案

React 不允许您在其他钩子(Hook)之前提前返回。如果一个组件执行的 hooks 比以前的渲染少,你会得到以下错误:

Invariant Violation: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

React 无法区分 Hook 调用之前的提前返回和因其他原因而有条件的 Hook 调用之间的区别。例如,如果您对 useState 进行了 3 次调用,有时您会在第二次调用后返回,React 无法判断您是在第二次调用 useState 后返回还是将围绕第一次或第二次 useState 调用的条件,因此它无法可靠地知道它是否为 执行的两次 useState 调用返回了正确的状态 发生。

下面是一个示例,您可以使用它来查看此错误(单击“增量状态 1”按钮两次以获取错误):

import React from "react";
import ReactDOM from "react-dom";

function App() {
  const [state1, setState1] = React.useState(1);
  if (state1 === 3) {
    return <div>State 1 is 3</div>;
  }
  const [state2, setState2] = React.useState(2);
  return (
    <div className="App">
      <div>State 1: {state1}</div>
      <div>State 2: {state2}</div>
      <button onClick={() => setState1(state1 + 1)}>Increment State 1</button>
      <button onClick={() => setState2(state2 + 1)}>Increment State 2</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit Early return with hooks

我建议的替代方法是将提前返回后的部分分离到它自己的组件中。早期返回后该部分所需的任何内容都作为 props 传递给新组件。

在我的示例中,它可能如下所示:

import React from "react";
import ReactDOM from "react-dom";

const AfterEarlyReturn = ({ state1, setState1 }) => {
  const [state2, setState2] = React.useState(2);
  return (
    <div className="App">
      <div>State 1: {state1}</div>
      <div>State 2: {state2}</div>
      <button onClick={() => setState1(state1 + 1)}>Increment State 1</button>
      <button onClick={() => setState2(state2 + 1)}>Increment State 2</button>
    </div>
  );
};
function App() {
  const [state1, setState1] = React.useState(1);
  if (state1 === 3) {
    return <div>State 1 is 3</div>;
  }
  return <AfterEarlyReturn state1={state1} setState1={setState1} />;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit Early return with hooks

关于javascript - 你能用 React hooks 提前回来吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54938236/

相关文章:

css - 对不同路线上的组件使用不同的样式?根据路线隐藏和显示数据

javascript - React 钩子(Hook)中的 `useState(null)[1]` 是什么?

javascript - 如何将事件监听器附加到 JavaScript 变量

javascript - 入门...通过 Javascript 的 Youtube API 提供最新上传的视频、标题和描述

node.js - 将 Recharts.js 库导入 jsx react 文件

javascript - 在 ssr 应用程序中单击时,react-router-dom <Link/> 会清除 {history,match,location} 属性

javascript - Sencha 触摸2 : How to override back button on Navigation View

javascript - 获取 http/https 协议(protocol)以匹配 maps.google.com 的 &lt;iframe&gt;

reactjs - 如何使用 React Hooks 更新依赖于其他状态的状态

reactjs - 在 React Hooks 中输入时,如何阻止 Editor draftJS 光标跳转到文本开头?