Entendendo "React.memo"

3 de dezembro de 2024

React.memo é uma função do React usada para otimizar a renderização de componentes funcionais. Com ela, podemos evitar re-renderizações desnecessárias quando as props não mudaram ajudando a melhorar a performance da aplicação.

Mas antes de sair usando, é importante entender como funciona e quando realmente vale a pena aplicar.

O que é React.memo?

É uma higher-order component (HOC) que memoriza a renderização de um componente com base nas props recebidas.

const MeuComponente = React.memo((props) => {
  return <div>{props.valor}</div>
})

Exemplo prático (sem React.memo)

function Botao({ onClick, label }) {
  console.log('Renderizou: ' + label)
  return <button onClick={onClick}>{label}</button>
}

function App() {
  const [count, setCount] = useState(0)

  return (
    <>
      <h1>Contador: {count}</h1>
      <Botao onClick={() => setCount(count + 1)} label="Incrementar" />
      <Botao onClick={() => alert('Olá!')} label="Mostrar alerta" />
    </>
  )
}

Toda vez que o contador muda, os dois botões são re-renderizados, mesmo que suas props não tenham mudado.

Usando React.memo

const Botao = React.memo(function Botao({ onClick, label }) {
  console.log('Renderizou: ' + label)
  return <button onClick={onClick}>{label}</button>
})

Agora, cada botão só será renderizado novamente se suas props mudarem.

Comparação automática de props

Por padrão, React.memo faz uma comparação rasa (shallow) das props. Se for um objeto, array ou função nova a cada render, mesmo com o mesmo conteúdo, o React vai re-renderizar.

Exemplo que ainda re-renderiza:

<Botao onClick={() => alert('oi')} label="Clique" />

Aqui, onClick é uma função nova a cada render, então o React.memo não consegue evitar a re-renderização.

Solução:

Use useCallback para manter a função estável:

const handleClick = useCallback(() => alert('oi'), [])
<Botao onClick={handleClick} label="Clique" />

Comparação customizada

Você pode passar uma função personalizada para comparar as props:

const MeuComponente = React.memo(
  (props) => {
    return <div>{props.valor}</div>
  },
  (prevProps, nextProps) => {
    return prevProps.valor === nextProps.valor
  }
)

Útil quando você quer ignorar mudanças que não afetam o UI, ou quando está lidando com objetos aninhados.

Conclusão

React.memo é uma ferramenta poderosa, mas como toda otimização, só faz sentido quando resolve um problema real. Use com consciência, após identificar re-renderizações desnecessárias que estão afetando a performance.