O que são componentes puros e impuros e como usa-los no React

Hoje iremos entender o que são componentes puros e impuros e como usa-los no React. Como já sabemos no Javascript existem funções puras e impuras, nos componentes do React não é diferente. Seguindo a mesma premissa, ao criar componentes que tenham ao máximo funções puras, pode-se evitar bugs e problemas na manutenção do código a maneira que o projeto cresce.

Caso não lembre ou não saiba o que são funções puras e impuras leia: O que são funções puras e impuras – FrontMaster

O React ele foi criado em cima do conceito de funções puras. A medida que os componentes são criado o React pressupõe que é uma função pura. Então sempre seu componente deve ter o mesmo retorno com as mesmas entradas, lembrando que esse é um dos requisitos para ser uma função pura. Abaixo mostrarei um exemplo retirado da documentação do React.

Componentes puros e impuros

let guest = 0;

function Cup() {
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  );
}
componente impuro
Retorno

Ao observarmos, cada renderização do componente Cup o valor é diferente, isso é ruim pois quebra um dos requisitos de ser uma função pura, não ter o valor final previsível. Então caso esse componente esteja em outra página o valor de retorno será diferente, pois cada chamada do componente ele retornara um JSX diferente. Vamos ajustar o código para ele depender apenas do parâmetro para ela modificar apenas o próprio escopo e não o escopo global da aplicação. Nessa situação acima o componente modifica uma variável fora do seu escopo.

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup guest={1} />
      <Cup guest={2} />
      <Cup guest={3} />
    </>
  );
}
componente puro
Retorno

Para o componente ser puro ele não pode alterar variáveis ou objetos que existam antes da renderização. Quando dada as mesmas entradas o componente dever sempre retornar os mesmo resultado. Caso isso não ocorra a função não é pura.

Caso necessário mudar algo e não é possível usando o manipulador de eventos, utilize o useEffect como última opção.

O outro componente não pode ser uma dependência para renderizar o componente.

Não se pode alterar os valores que o componente precisa para renderizar como props, estados e contextos. Devemos tratar esses valores apenas como leitura. Quando necessário alterar algo, crie um estado para isso e não gravar diretamente em uma variável.

Segundo a documentação: Você nunca deve alterar variáveis ou objetos preexistentes enquanto o componente estiver sendo renderizado.

Referência: react.dev