Re-renderizaciones innecesarias de TextField
He notado un problema en el que todos los componentes dentro del mismo padre ( aplicación en el ejemplo siguiente) se volverán a procesar cuando cambien los estados / accesorios no relacionados, lo que hace que la página o los formularios sean más lentos.
He seguido muchos consejos, como memorizar controladores de eventos y accesorios, pero los componentes no relacionados aún se vuelven a renderizar. Estoy perplejo. ¿Qué no entiendo sobre React?
[ CodeSandbox ] En el depurador de React, habilite: Resalte las actualizaciones cuando los componentes se procesen
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>
</>
);
}
Respuestas
Las herramientas de depuración tienen errores con respecto a los componentes memorizados. Cuando memoriza componentes, en realidad no se vuelven a renderizar, pero las herramientas de depuración los resaltan de todos modos (consultehttps://github.com/facebook/react/issues/19778).
Para probar realmente la re-renderización, cambie el valor de estado predeterminado para la segunda entrada (que se renderiza muchas veces) a algo como "prueba", luego coloque un componente console.logmemorizado dentro MyTextInputpara ver cuáles se están volviendo a renderizar:
const MyTextInput = React.memo((props) => {
console.log(props.value);
return (
<TextField
variant={"outlined"}
onChange={props.onChange}
value={props.value}
disabled={props.disabled}
/>
);
});
Puede ver que imprime el valor de "prueba" una vez para todas las segundas entradas cuando se procesan por primera vez, luego, mientras escribe la primera, no registra todas las segundas entradas console.loggracias a la memorización.