Javascript 你能早点回来吗?

Javascript 你能早点回来吗?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,React文件明确指出:,原因是React使用调用钩子的顺序来注入正确的值 我理解这一点,但现在我的问题是,是否可以从带有挂钩的函数组件中提前返回 这样的事情允许吗 import React from 'react'; import { useRouteMatch, Redirect } from 'react-router'; import { useSelector } from 'react-redux'; export default function Component() {

React文件明确指出:,原因是React使用调用钩子的顺序来注入正确的值

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

这样的事情允许吗

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} />;
}
从“React”导入React;
从“react router”导入{useRouteMatch,Redirect};
从'react redux'导入{useSelector};
导出默认函数组件(){
const{match}=useRouteMatch({path:'/:some/:thing'});
如果(!匹配)返回;
const{some,thing}=match.params;
const state=useSelector(stateSelector(some,thing));
返回;
}
从技术上讲,
useSelector
hook是有条件调用的,但是调用它们的顺序在渲染之间不会改变(即使可能会少调用一个hook)


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

React不允许您在其他挂钩之前提前返回。如果组件执行的钩子数少于上一个渲染,则会出现以下错误:

不变冲突:渲染的钩子比预期的少。这可能是由意外的提前返回语句引起的

React无法区分提前返回和条件钩子调用之间的区别。例如,如果您有3个对
useState
的调用,并且有时在第二个调用之后返回,React无法判断您是在第二个
useState
调用之后返回,还是在第一个或第二个
useState
调用周围设置了条件,因此,它无法可靠地知道它是否为两个
useState
调用返回了正确的状态,而确实发生了

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

从“React”导入React;
从“react dom”导入react dom;
函数App(){
const[state1,setState1]=React.useState(1);
如果(状态1==3){
返回状态1为3;
}
const[state2,setState2]=React.useState(2);
返回(
状态1:{state1}
状态2:{state2}
设置状态1(状态1+1)}>增量状态1
设置状态2(状态2+1)}>增量状态2
);
}
const rootElement=document.getElementById(“根”);
ReactDOM.render(

我建议的另一种方法是将提前返回后的部分分离到它自己的组件中。提前返回后的部分所需的任何东西都作为道具传递给新组件

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

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”导入React;
从“react dom”导入react dom;
const AfterEarlyReturn=({state1,setState1})=>{
const[state2,setState2]=React.useState(2);
返回(
状态1:{state1}
状态2:{state2}
设置状态1(状态1+1)}>增量状态1
设置状态2(状态2+1)}>增量状态2
);
};
函数App(){
const[state1,setState1]=React.useState(1);
如果(状态1==3){
返回状态1为3;
}

return

如前所述,您不能在组件内有条件地运行钩子。但您可以将可能被视为自定义钩子的呈现函数传递给其他组件,并且仍然可以访问当前作用域。因此,不要拆分组件,而是像这样使用实用程序组件:

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

const HooksHost = ({ children }) => children();

function App() {
  const [state1, setState1] = React.useState(1);

  if (state1 === 3) {
    return <div>State 1 is 3</div>;
  }

  return (
    <HooksHost>
      {/* should be named to pass lint rule that checks if it starts from 'use' then it is custom hook */}
      {function useHooks() {
        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>
        );
      }}
    </HooksHost>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
从“React”导入React;
从“react dom”导入react dom;
const HooksHost=({children})=>children();
函数App(){
const[state1,setState1]=React.useState(1);
如果(状态1==3){
返回状态1为3;
}
返回(
{/*应命名为传递lint规则,该规则检查它是否从“use”开始,然后它是自定义挂钩*/}
{函数useHooks(){
const[state2,setState2]=React.useState(2);
返回(
状态1:{state1}
状态2:{state2}
设置状态1(状态1+1)}>
增量状态1
设置状态2(状态2+1)}>
增量状态2
);
}}
);
}
const rootElement=document.getElementById(“根”);
render(,rootElement);

您在自己的问题中有一个答案-这是不允许的,因为
React使用您调用hook的顺序来注入正确的值
。它实际上可能在您的情况下起作用,您将得到的警告只是一个警告,而不是错误。但是您可能会在以后陷入错误,因为您实际上忘记了这一点组件,并决定添加更多挂钩或重新安排条件。这是一个好主意,但它不够干净,所以我必须编写使其更干净
import React from "react";
import ReactDOM from "react-dom";

const HooksHost = ({ children }) => children();

function App() {
  const [state1, setState1] = React.useState(1);

  if (state1 === 3) {
    return <div>State 1 is 3</div>;
  }

  return (
    <HooksHost>
      {/* should be named to pass lint rule that checks if it starts from 'use' then it is custom hook */}
      {function useHooks() {
        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>
        );
      }}
    </HooksHost>
  );
}

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