React: eslint-plugin-react-hooks: Fehler 'Hook wird bedingt aufgerufen' außerhalb der Bedingung

Erstellt am 19. Sept. 2019  ·  4Kommentare  ·  Quelle: facebook/react

Möchten Sie eine Funktion anfordern oder einen Fehler melden?

BUG (möglicherweise)

Wie ist das aktuelle Verhalten?

Das Plugin zeigt diesen Fehler an:

React Hook "useState" wird bedingt aufgerufen. React Hooks müssen in jedem Komponenten-Rendering in genau derselben Reihenfolge aufgerufen werden. Haben Sie nach einer frühen Rückkehr versehentlich einen React Hook angerufen? (React-Hooks / Rules-of-Hooks) Eslint

Aber ich glaube nicht, dass ich irgendwelche Haken bedingt anrufe.

Der Code:

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

Was ist das erwartete Verhalten?

Das Plugin würde den Fehler in dieser Situation nicht anzeigen.

Welche Versionen von React und welcher Browser / welches Betriebssystem sind von diesem Problem betroffen?

image

ESLint Rules Bug

Hilfreichster Kommentar

Alle 4 Kommentare

Ich habe das für dieses spezielle Beispiel bemerkt:

pathsFromStartToEnd ist 3
allPathsFromStartToEnd ist 2

auch possiblyHasEarlyReturn ist true


Dieser bestimmte Fehler wird gemeldet, wenn pathsFromStartToEnd und allPathsFromStartToEnd ungleich sind.

Siehe RulesOfHooks.js Zeile 404


Wenn Sie den Code innerhalb der for..in -Schleife in eine separate Funktion abstrahieren, verschwindet der Flusenfehler.

In diesem Fall sind pathsFromStartToEnd und allPathsFromStartToEnd beide gleich 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);

Ich bin mir immer noch nicht sicher warum.

@gaearon , ich habe eine MR-Adressierung erstellt und dieses Problem behoben (# 16853).

Der Hauptgrund dafür ist, dass der Wert von allPathsFromStartToEnd falsch berechnet wird.
In diesem Beispiel sollte die Anzahl der Pfade von Anfang bis Ende 3 betragen, die Funktion gibt jedoch 2 zurück.

Der Grund dafür ist das fehlerhafte Zwischenspeichern von zyklischen Pfaden. Beim normalen Durchlaufen von Graphen benötigen wir also auch den Pfadverlauf, es wird jedoch nur eine Liste der zyklischen Elemente benötigt, und die Elemente, die zu diesem Pfad führen, sind nicht bekannt.
Wenn eine Bedingung in einem for...in obj , verlieren wir möglicherweise einige Pfade, basierend auf der Richtung.

Dies ist immer noch ein Problem mit 2.4.0, ein bisschen einfacher Repro:

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

Kann # 16853 erneut geöffnet werden?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen