Restitutions inutiles de TextField

Nov 06 2020

J'ai remarqué un problème où chaque composant du même parent ( application dans l'exemple ci-dessous) sera renvoyé lorsque des états / accessoires non liés changent, rendant la page / les formulaires plus lents.

J'ai suivi de nombreux conseils tels que la mémorisation des gestionnaires d'événements et des accessoires, mais les composants non liés sont toujours restitués. Je suis perplexe. Qu'est-ce que je ne comprends pas à propos de React?

[ CodeSandbox ] Dans le débogueur React, activer: mettre en surbrillance les mises à jour lors du rendu des composants

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

Réponses

1 Jayce444 Nov 06 2020 at 06:52

Les outils de débogage sont buggés en ce qui concerne les composants mémorisés. Lorsque vous mémorisez des composants, ils ne sont pas réellement rendus à nouveau, mais les outils de débogage les mettent quand même en surbrillance (voirhttps://github.com/facebook/react/issues/19778).

Pour tester réellement le re-rendu, changez la valeur d'état par défaut pour la deuxième entrée (qui est rendue beaucoup de fois) en quelque chose comme "test", puis placez un à l' console.logintérieur d'un MyTextInputcomposant mémorisé pour voir lesquels sont réellement re-rendus:

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

Vous pouvez voir qu'il imprime une fois la valeur "test" pour toutes les secondes entrées lors du premier rendu, puis lorsque vous tapez la première, il ne consigne pas toutes les secondes entrées console.loggrâce à la mémorisation.