您可以使用React钩子早日返回吗? [英] Can you early return with React hooks?

查看:43
本文介绍了您可以使用React钩子早日返回吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

React文档明确指出,

我建议的另一种方法是将早期返回的部分分成自己的部分.提早返回后该部分所需的所有内容都将作为道具传递给新组件.

在我的示例中,它可能类似于以下内容:

  import从反应"中反应;从"react-dom"导入ReactDOM;const AfterEarlyReturn =({state1,setState1})=>{const [state2,setState2] = React.useState(2);返回 (< div className ="App">< div>状态1:{state1}</div>< div>状态2:{state2}</div>< button onClick = {()=>setState1(state1 + 1)}>增量状态1</button>< button onClick = {()=>setState2(state2 + 1)}>递增状态2</button></div>);};函数App(){const [state1,setState1] = React.useState(1);如果(state1 === 3){返回< div>状态1为3</div> ;;}返回< AfterEarlyReturn state1 = {state1} setState1 = {setState1}/> ;;}const rootElement = document.getElementById("root");ReactDOM.render(< App/> ;, rootElement); 

The React docs make it clear that calling hooks conditionally will not work. From the original React hooks presentation, the reason is because React uses the order you call hooks to inject the correct value.

I understand this, but now my question is whether or not it's okay to early return from within a function component with hooks.

So is something like this allowed?:

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} />;
}

Technically, the useSelector hook is being called conditionally, however the order when they are called doesn't change between renders (even though it's possible that one less hook will be called).

If this isn't allowed can you explain why it isn't allowed and provide general alternative approaches to early returning in a function component with hooks?

解决方案

React does not allow you to do an early return prior to other hooks. If a component executes fewer hooks than a previous render, you will get the following error:

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

React can't tell the difference between an early return and a conditional hook call. For instance, if you have 3 calls to useState and you sometimes return after the second one, React can't tell whether you returned after the second useState call or if you put a condition around the first or second useState call, so it can't reliably know whether or not it is returning the correct state for the two useState calls that did occur.

Here's an example that you can use to see this error in action (click the "Increment State 1" button twice to get the error):

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);

The alternative approach I would recommend is to separate the portion after the early return into its own component. Anything needed by the portion after the early return gets passed to the new component as props.

In the case of my example, it could look like the following:

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);

这篇关于您可以使用React钩子早日返回吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆