Можете ли вы рано вернуться с крючками React? - PullRequest
0 голосов
/ 01 марта 2019

Документы React дают понять, что условный вызов хуков не будет работать . Из оригинальной презентации хуков React причина была в том, что React использует порядок, который вы называете хуками, чтобы ввести правильное значение.

Я понимаю это, но теперь мой вопрос заключается в том, нормально ли этодосрочное возвращение из компонента функции с перехватчиками.

Итак, допускается что-то вроде этого:

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

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

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


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

Технически, перехват useSelector вызывается условно, однако порядок, когда ониnamed не изменяется между рендерами (даже если возможно, что будет вызван на один хук меньше).

Если это не разрешено, вы можете объяснить , почему это не разрешено, и предоставитьобщие альтернативы подходы к раннему возврату в компоненте функции с хуками?

1 Ответ

0 голосов
/ 10 июля 2019

React не позволяет вам сделать ранний возврат до других хуков.Если компонент выполняет меньше хуков, чем предыдущий рендер, вы получите следующую ошибку:

Инвариантное нарушение: рендеринг меньше хуков, чем ожидалось.Это может быть вызвано случайным оператором раннего возврата.

React не может определить разницу между ранним возвратом и условным вызовом ловушки.Например, если у вас есть 3 вызова на useState, и вы иногда возвращаетесь после второго, React не может определить, вернулись ли вы после второго useState вызова или если вы поставили условие вокруг первого или второго useStatecall, поэтому он не может достоверно знать, возвращает ли он правильное состояние для двух 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

Альтернативный подход, который я рекомендовал бысостоит в том, чтобы отделить часть после досрочного возврата в свой собственный компонент.Все, что нужно части после раннего возврата, передается новому компоненту в качестве реквизита.

В моем примере это может выглядеть следующим образом:

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

...