Website-Suche

reactjs - useEffect wird nicht aktualisiert, wenn setState in der Child-Komponente ausgeführt wird


Ich erstelle ein Tic-Tac-Toe-Spiel mit React und habe die setState-Funktion des übergeordneten Elements, um das Spielfeld zu ändern, an die Kindkomponente weitergegeben.

Danach habe ich ein useEffect im übergeordneten Komponent (useEffect(() => ... , [board])) eingefügt, um eine Aktion auszuführen, wann immer sich dieser Zustand ändert. Aber es passiert nichts, wenn ich das setState innerhalb des Kindes verwende. Das untenstehende console.log zeigt true an, und das ist wahrscheinlich der Grund, warum sich das useEffect nicht aktualisiert.

function handleClick(_, i:number) {

    setBoard(prevBoard => {
  
      const newBoard = board

      newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
  
      console.log(newBoard == prevBoard)
  
      return newBoard
  
    })

...

}

Antwort #1

Das unten stehende console.log zeigt true an, und das ist wahrscheinlich der Grund, warum der useEffect nicht aktualisiert wird.

Genau das ist es. Der State in React ist dazu gedacht, unveränderlich zu sein. Wenn Sie setBoard aufrufen, wird React den alten State mit dem neuen State mithilfe einer Object.is-Prüfung vergleichen (die ähnlich wie === ist). Wenn sie gleich sind, sieht es so aus, als hätte sich nichts geändert, und React überspringt das erneute Rendern. React wird die Eigenschaften innerhalb Ihres States nicht überprüfen, um zu sehen, ob sie sich geändert haben, da dies teuer sein könnte.

Stellen Sie stattdessen sicher, dass Sie einen neuen Zustand erstellen, anstatt den alten zu ändern:

setBoard(prevBoard => {
  const newBoard = [...board]; // <--- creating a shallow copy
  newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
  return newBoard
})

Antwort #2

Was React betrifft, wird der Zustand tatsächlich nicht aktualisiert, weil es immer noch dieselbe Objektreferenz ist. Du veränderst den Zustand, anstatt eine neue Instanz zu erstellen.

Dies kopiert das Array nicht, es zeigt nur eine neue Variable auf dieselbe Referenz:

const newBoard = board

Jede Änderung an newBoard wird also direkt an der State-Instanz vorgenommen (sie wird verändert). Erstelle stattdessen ein neues Array mit Kopien der Elemente des bestehenden Arrays (die selbst Referenzen sein können, aber das ist oft ein Randfall und sollte hier kein Problem darstellen):

const newBoard = [...board]

In diesem Fall ist newBoard ein völlig neues Objekt-Referenz, also wenn es auf den State gesetzt wird, wird React es als aktualisierten State sehen.