TextField Unnötiges Rendern

Nov 06 2020

Ich habe ein Problem festgestellt, bei dem jede Komponente innerhalb desselben übergeordneten Elements ( App im folgenden Beispiel) erneut gerendert wird, wenn sich nicht verwandte Zustände / Requisiten ändern, wodurch die Seite / Formulare langsamer wahrgenommen werden.

Ich habe viele Ratschläge befolgt, z. B. das Auswendiglernen von Ereignishandlern und Requisiten, aber nicht verwandte Komponenten werden immer noch neu gerendert. Ich bin ratlos. Was verstehe ich nicht über Reagieren?

[ CodeSandbox ] Aktivieren Sie im React-Debugger Folgendes : Markieren Sie Aktualisierungen, wenn Komponenten gerendert werden

import React, { useMemo, useState } from "react";
import { TextField } from "@material-ui/core";

function MyTextInput(props) {
  return (
    <TextField
      variant={"outlined"}
      onChange={props.onChange}
      value={props.value}
    />
  );
}

export default function App() {
  const [exampleTextValue1, setExampleTextValue1] = useState("");
  const [exampleTextValue2, setExampleTextValue2] = useState("");

  const handleChange1 = useMemo(
    () => (event) => setExampleTextValue1(event.target.value),
    []
  );

  const handleChange2 = useMemo(
    () => (event) => setExampleTextValue2(event.target.value),
    []
  );

  return (
    <>
      <div>
        Change me:
        <MyTextInput value={exampleTextValue1} onChange={handleChange1} />
      </div>

      <div>
        Unrelated inputs. Should not re-render:
        <MyTextInput value={exampleTextValue2} onChange={handleChange2} />
        <MyTextInput value={exampleTextValue2} onChange={handleChange2} />
        {/*  to feel the impact, copy the above line like 98 more times  */}
      </div>
    </>
  );
}

Antworten

1 Jayce444 Nov 06 2020 at 06:52

Die Debugger-Tools sind in Bezug auf gespeicherte Komponenten fehlerhaft. Wenn Sie Komponenten auswendig lernen, werden sie nicht erneut gerendert, aber die Debugging-Tools heben sie trotzdem hervor (siehe)https://github.com/facebook/react/issues/19778).

Um das erneute Rendern tatsächlich zu testen, ändern Sie den Standardstatuswert für die zweite Eingabe (die häufig gerendert wird) in "Test" und console.logfügen Sie dann eine in eine gespeicherte MyTextInputKomponente ein, um zu sehen, welche tatsächlich neu gerendert werden:

const MyTextInput = React.memo((props) => {
  console.log(props.value);
  return (
    <TextField
      variant={"outlined"}
      onChange={props.onChange}
      value={props.value}
      disabled={props.disabled}
    />
  );
});

Sie können sehen, dass der "Test" -Wert einmal für alle zweiten Eingaben beim ersten Rendern gedruckt wird. Wenn Sie dann die erste eingeben, werden console.logdank der Memoisierung nicht alle zweiten Eingaben protokolliert .