React: eslint-plugin-react-hooks: 'Hook está sendo chamado condicionalmente' erro fora da condição

Criado em 19 set. 2019  ·  4Comentários  ·  Fonte: facebook/react

Você quer solicitar um recurso ou relatar um bug ?

BUG (possivelmente)

Qual é o comportamento atual?

O plugin está mostrando este erro:

O React Hook "useState" é chamado condicionalmente. Os Ganchos React devem ser chamados exatamente na mesma ordem em cada renderização de componente. Você acidentalmente chamou um React Hook após um retorno antecipado? (react-hooks / rules-of-hooks) eslint

Mas não acho que estou chamando nenhum gancho condicionalmente.

O código:

https://codesandbox.io/s/exciting-bhabha-mqj7q

function App(props) {
  const someObject = { propA: true, propB: false };

  for (const propName in someObject) {
    if (propName === true) {
      console.log("something");
    } else {
      console.log("whatever");
    }
  }

  // THE PLUGIN ERROR MSG ON THIS useState
  const [myState, setMyState] = useState(null);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

image

Qual é o comportamento esperado?

O plugin não mostraria o erro nesta situação.

Quais versões do React e quais navegadores / sistemas operacionais são afetados por esse problema?

image

ESLint Rules Bug

Comentários muito úteis

Todos 4 comentários

Percebi que para este exemplo específico:

pathsFromStartToEnd é 3
allPathsFromStartToEnd é 2

também possiblyHasEarlyReturn é true


Este erro específico é relatado quando pathsFromStartToEnd e allPathsFromStartToEnd são desiguais.

Consulte a linha 404 de RulesOfHooks.js


Se você abstrair o código dentro do loop for..in em uma função separada, o erro de lint desaparece.

Neste caso, pathsFromStartToEnd e allPathsFromStartToEnd ambos iguais a 2 :

  const someObject = { propA: true, propB: false };
  const someFunction = (propName) => {
    if (propName === true) {
      console.log("something");
    } else {
      console.log("whatever");
    }
  }
  for (const propName in someObject) {
    someFunction(propName)
  }
  const [myState, setMyState] = useState(null);

Ainda não tenho certeza do porquê.

@gaearon , criei um MR abordando e corrigindo esse problema (# 16853).

A principal razão para isso acontecer é que o valor de allPathsFromStartToEnd foi calculado incorretamente.
Neste exemplo, o número de caminhos do início ao fim deve ser 3, mas a função retorna 2.

A razão pela qual isso acontece é devido ao armazenamento em cache defeituoso de caminhos cíclicos. Portanto, na travessia normal de um gráfico, precisamos também do histórico do caminho, mas leva apenas uma lista de elementos cíclicos e os elementos que levam a esse caminho não são conhecidos.
Como resultado, quando uma condição é usada em for...in obj , com base na direção, podemos perder alguns caminhos.

Este ainda é um problema com o 2.4.0, uma reprodução um pouco mais simples:

import * as React from "react";

function Component() {
  let isLastEven = false;
  for (let x of [1, 2, 3]) {
    if (x % 2 == 0) {
      isLastEven = true;
    } else {
      isLastEven = false;
    }
  }
  let y = React.useMemo(() => 1, []);
  return <div>{y}</div>;
}

pode # 16853 ser reaberto?

Esta página foi útil?
0 / 5 - 0 avaliações