TextField Renderizza non necessari

Nov 06 2020

Ho notato un problema in cui ogni componente all'interno dello stesso genitore ( App nell'esempio sotto) verrà rieseguito quando cambiano stati / oggetti di scena non correlati, rendendo la pagina / i moduli più lenti.

Ho seguito molti consigli come la memorizzazione di gestori di eventi e oggetti di scena, ma i componenti non correlati vengono ancora riprodotti. Sono perplesso. Cosa non capisco di React?

[ CodeSandbox ] Nel debugger di React, abilita: Evidenzia gli aggiornamenti durante il rendering dei componenti

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

Risposte

1 Jayce444 Nov 06 2020 at 06:52

Gli strumenti del debugger sono buggati per quanto riguarda i componenti memoizzati. Quando si memorizzano i componenti, in realtà non vengono nuovamente renderizzati, ma gli strumenti di debug li evidenziano comunque (vederehttps://github.com/facebook/react/issues/19778).

Per testare effettivamente il re-rendering, modificare il valore di stato predefinito per il secondo input (che viene reso molte volte) in qualcosa come "test", quindi inserire un componente console.logall'interno di un memo MyTextInputper vedere quali vengono effettivamente ri-renderizzati:

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

Puoi vedere che stampa il valore "test" una volta per tutti i secondi input quando vengono renderizzati per la prima volta, quindi mentre digiti il ​​primo, non registra tutti i secondi input console.loggrazie alla memoizzazione.