useEffect vs useLayoutEffect: Quando usar cada um?
Esse artigo é uma tradução do artigo original useEffect vs useLayoutEffect criado por Kent C. Dodds.
Ambas opções podem ser usadas para fazer a mesma coisa, mas elas tem casos de uso ligeiramente diferentes. Então, aqui estão algumas regras para você considerar ao decidir qual React Hook usar.
useEffect
99% das vezes é esse que você precisará usar. Quando seus hooks são estáveis e você refatora as suas class components para hooks, aos poucos você irá mudar códigos de componentDidMount
, componentDidUpdate
e componentWillUnmount
para useEffect
.
O único problema dele é ser apenas executado após o React renderizar seu componente, garantindo que ele não bloqueie a renderização do navegador. Isso é diferente do comportamento de class components onde componentDidMount
e componentDidUpdate
rodam de forma síncrona após a renderização. É mais eficiente dessa maneira e na maioria das vezes é isso que você precisará.
Entretanto, se o uso desse hook estiver mudando o DOM(via DOM node ref) e a mutação do DOM alterar a aparência do nó do DOM entre o momento que ele é renderizado e o momento que seu hook o altera, então você não deseja usar o useEffect
. Você na verdade quer usar o useLayoutEffect
. Caso contrário, o usuário poderá ver uma mudança rápida na interface quando suas mudanças do DOM forem realizadas. Essa é praticamente a única vez que você deseja evitar useEffect
e usar useLayoutEffect
em vez disso.
useLayoutEffect
Executado de forma síncrona imediatamente após o React fazer todas as alterações no DOM. Pode ser útil se você precisar fazer medições DOM (como obter a posição de rolagem ou outros estilos para um elemento) e depois fazer alterações no DOM ou acionar uma nova renderização síncrona atualizando o estado.
No que diz respeito ao momento, ele funciona da mesma forma que componentDidMount
e componentDidUpdate
. Seu código é executado imediamente após o DOM ser atualizado, mas antes que o navegador tenha a chance de "renderizar" essas alterações (o usuário não vê as atualizações até que o navegador tenha re-renderizado).
Resumo
-
useLayoutEffect
: Se você precisar alterar o DOM e/ou precisar realizar medições. -
useEffect
: Se você não precisa interagir com o DOM ou suas alterações no DOM não são observáveis (sério, na maioria das vezes você deve usar isso).
Um caso diferente
Um caso onde você possa querer usar useLayoutEffect
ao invés de useEffect
é quando você está atualizando um valor(como ref
) e você quer ter certeza de que está atualizado antes que qualquer outro código seja executado. Exemplo:
const ref = React.useRef()
React.useEffect(() => {
ref.current = 'valor qualquer'
})
// depois, em outro hook ou algo do tipo
React.useLayoutEffect(() => {
console.log(ref.current) // <-- isso aqui loga o valor antigo pois é executado primeiro!
})
Em casos como esse, use useLayoutEffect
.
Conclusão
É tudo sobre padrões. O comportamento padrão é permitir que o navegador renderize novamente com base nas atualizações do DOM antes que o React execute seu código. Isso significa que seu código não bloqueará o navegador e o usuário verá as atualizações do DOM mais cedo. Portanto, fique com useEffect
na maioria das vezes.