javascript - ¿Cómo evitar re-renderizados innecesarios para "componentes estáticos" en un componente funcional de React?
Tengo un componente funcional de React que muestra una lista de etiquetas y publicaciones, además de algunos textos/elementos estáticos. Almaceno la etiqueta seleccionada actualmente en un estado usando el hook useState. Las publicaciones se obtienen usando el hook useQuery de Apollo con la variable tag. El usuario debería poder seleccionar una etiqueta y esto reemplazará el estado actual de tag, por lo que el useQuery(POSTS_QUERY) se volverá a ejecutar con la nueva variable tag.
const onTagSelectChange = (window: Window,
router: NextRouter,
name: string,
checked: boolean,
tagSetter: React.Dispatch<React.SetStateAction<string>>) => {
if (checked) {
setTagQueryInUrl(window, router, name)
tagSetter(name)
} else {
setTagQueryInUrl(window, router, null)
tagSetter(null)
}
}
const NewsList: NextPage = () => {
const router = useRouter()
const query = router.query as Query
// store tag in state
// initialize tag from `tag` query
const [tag, setTag] = useState(query.tag)
const { data: postsData, loading: postsLoading, error: postsError } = useQuery(
POSTS_QUERY,
{
variables: {
tag: tag
}
}
)
const { data: tagsData, loading: tagsLoading, error: tagsError } = useQuery(TAGS_QUERY)
// show error page if either posts or tags query returned error
if (postsError || tagsError) {
return <Error statusCode={500} />
}
return (
<div>
<h1>Here we have list of news, and I should not re-render everytim :(</h1>
<Tags
loading={tagsLoading}
data={tagsData}
isChecked={(name) => name === tag}
onChange={(name, checked) => onTagSelectChange(window, router, name, checked, setTag)}
/>
<Posts loading={postsLoading} data={postsData} />
</div>
)
}
Mi pregunta es, ¿por qué mi bloque h1 sigue volviéndose a renderizar aunque no le pase nada? ¿O estoy entendiendo completamente mal cómo funciona React?
Respuesta #1
Los componentes de React se vuelven a renderizar cada vez que cambian su estado o propiedades. Si estoy entendiendo esto correctamente, entonces estás cambiando la etiqueta en el estado cada vez que cambia la URL y, por lo tanto, haciendo que el componente se vuelva a renderizar a sí mismo.
Respuesta #2
Como tu estado se declara en tu componente NewsList, cualquier cambio de estado (como otro usuario indicó en su respuesta) desencadenará un re-renderizado de todo el componente (NewsList) y no solo de los componentes a los que les has pasado tu estado (por lo tanto, al <h1> estático que tienes allí).
Si hay partes de este componente que no tienen nada que ver con este estado, puedes moverlas afuera para evitar la re-renderización.
Aunque, en casos como este, volver a renderizar tu <h1> no representa un costo para React. Deberías preocuparte y seguir este enfoque en componentes personalizados donde ocurren cosas más complejas (por ejemplo, poblando listas o calculando cosas, etc.). En esos casos, no quieres que todas estas cosas complejas sucedan de nuevo, si no se ven afectadas por un cambio en el estado del padre. También deberías siempre considerar si mover el componente afuera tiene sentido o si al hacerlo, complicas tu código.
Siempre debes encontrar un equilibrio entre un código bien organizado y eficiente.
