React: Realizando State Update de modo a evitar renderizações desnecessárias

Evitar renderização inútil é um tópico realmente importante para melhorar o desempenho de aplicações React, podendo ser, inclusive, um requisito para uma experiência de usuário satisfatória.

Há alguns anos eu estava criando um aplicativo web de pesquisa que possuía uma tela com N campos de entrada (sob demanda). Eu estava começando com React e, à primeira vista, pareceu-me uma boa estratégia manter o array de valores de entrada no estado do componente pai e apenas passar o callback de mudança de estado e o índice para seus filhos. Algo parecido com:

Mas essa abordagem revelou um desastre com N grande, cada dígito tem utilizava muita renderização gerando atraso. A fim de antecipar e evitar esse tipo de desastre, escrevi esse artigo.

Para atualizar estados em react temos um universo de possibilidades: contexto, redux, hooks, callback, e simples updates dentro do componente. Nós também podemos herdar Componente ou PureComponent, ou apenas usar componentes funcionais (ou talvez react.memo?). Ao escolher uma dessas combinações podemos estar fazendo renderizações desnecessárias, o que você provavelmente quer evitar.

Nesta confusão de possíveis combinações, vamos ver algumas mais usadas e entender o conceito por trás de cada uma.

Para obter um feedback visual sobre o que estamos fazendo, recomendo (e uso) React Highlight Update do React Developer Tool

  • Atualização simples do estado do componente interno (estado no componente)
  • Alterar estado com callback (estado no componente pai)
  • Component ou PureComponent?
  • Functional Components e React.memo
  • Atualização do estado com Redux
  • Atualização do estado com Hooks
  • Atualização do estado com Context

Atualização simples do estado do componente interno (estado no componente)

Vamos começar com a maneira mais simples de atualizar um react state, dentro de um componente React usando setState.

Essa é uma das melhores práticas para atualizar um estado, atualizando dentro do componente que tem o estado você irá renderizar somente ele. Isso ocorre porque um React Component é renderizado novamente quando seu estado muda ou seu estado pai é alterado. Visualmente nós temos.

Alterar estado com callback (estado no componente pai)

Por outro lado, podemos passar o estado como props e o setState como callback. É bastante comum e também é o exemplo no começo deste artigo. Isso pode ser um problema, porque cada atualização será no componente pai, e todos os seus filhos (exceto se usar react.memo ou estender PureComponent) serão atualizados também, provavelmente não é o que você deseja.

Observe que os componentes do redux não são renderizados novamente, Isso ocorre porque eles implementam o PureComponent, portanto, eles serão alterados somente se seus props forem alterados. Já que estamos falando disso…

Component ou PureComponent

Qual é a diferença afinal? O PureComponent é exatamente igual ao Component, exceto pelo fato de manipular o método shouldComponentUpdate para nós. Quando props ou estados mudam, PureComponent fará uma comparação shallow em props e state para verificar a necessidade da renderização. Portanto, um PureComponent não será necessariamente renderizado se seu pai estiver renderizando, na maioria dos casos, um Componente Puro só será renderizado se seus props mudarem ou seu estado mudar. A propósito, se estiver usando o PureComponent, certifique-se de que todos os componentes filhos também sejam puros.

Functional Component e React.memo

O componente funcional não pode estender o PureComponent, então como podemos ser salvos? O React 16.6.0 vem com o React.memo () e é um wrapper para o memoize de um componente funcional, então ele será renderizado apenas se seus props mudarem (ou se ele estiver usando hooks e mudar seu estado). Visualmente temos:

COMP – component, FUNC – functional component, COMP PURE – pure component, FUNC MEMO – functional component wrapped by React.memo()

Atualização de Estado com Redux

Para atualizar um estado usando o redux, precisamos nos preocupar com quais estados estamos mapeando para props dentro de mapStateToProps (). Cada alteração nesses estados renderizará novamente o componente que os mapeia. Vamos verificar a maneira errada:

Agora a maneira certa:

Então tudo que você precisa para obter uma boa performance com redux é CONECTE APENAS O QUE VOCÊ NECESSITA, nem mais, nem menos.

Atualização de Estado com Hooks

Com hooks temos o estado dentro do componente, é como o primeiro exemplo mas com componentes funcionais, essa é a beleza dos hooks! Então, o mesmo, é o melhor cenário.

Atualização de Estado com Context

Atualizar estado com Context é muito semelhante ao segundo exemplo, onde o estado pertence também será atualizado (e seus filhos também).

Published by

Marcello Marques

Full Stack Developer

Leave a Reply

Your email address will not be published. Required fields are marked *