useInsertionEffect
O useInsertionEffect
permite inserir elementos no DOM antes que qualquer efeito de layout seja acionado.
useInsertionEffect(setup, dependencies?)
Referência
useInsertionEffect(setup, dependencies?)
Chame useInsertionEffect para inserir estilos antes que quaisquer efeitos sejam ativados e que possam precisar ler o layout:
import { useInsertionEffect } from 'react';
// Na sua biblioteca CSS-em-JS
function useCSS(rule) {
useInsertionEffect(() => {
// ... injetar tags <style> aqui ...
});
return rule;
}
Parameters
-
setup
: A função que contém a lógica do seu Effect. A função de setup também pode opcionalmente retornar uma função cleanup. Quando o componente é adicionado ao DOM, porém antes de qualquer efeito de layout ser acionado, o React executará sua função de setup. Após cada re-renderização com as dependências alteradas, o React irá executar primeiro a função de cleanup (caso você a tenha fornecido) com os valores antigos, e depois executará sua função de setup com os novos valores. Quando o componente for removido do DOM, o React irá executar sua função de cleanup. -
opcional
dependencies
: A lista de todos os valores reativos referenciados no códigosetup
. Valores reativos incluem props, state, e todas as variáveis e funções declaradas diretamente dentro do corpo do seu componente. Caso seu linter esteja configurado para React, ele irá verificar se cada valor reativo está corretamente especificado como uma dependência. A lista de dependências deve ter um número constante de itens e ser escrita em linha como[dep1, dep2, dep3]
. O React irá comparar cada dependência com seu valor anterior utilizando o algoritmo de comparaçãoObject.is
. Se você não especificar as dependências, seu Effect será executado novamente após cada re-renderização do componente.
Retornos
useInsertionEffect
retorna undefined
.
Avisos
- Effects (efeitos) só são executados pelo cliente. Eles não são executados durante a renderização do servidor.
- Não é possível atualizar o estado de dentro do
useInsertionEffect
. - No momento em que
useInsertionEffect
é executado, as refs ainda não foram anexadas. - O
useInsertionEffect
pode ser utilizado antes ou depois do DOM ter sido atualizado. Você não deve confiar que o DOM seja atualizado em um determinado momento. - Ao contrário de outros tipos de Effects, que disparam a limpeza para cada Effect e depois a configuração para cada Effect,
useInsertionEffect
irá disparar tanto a limpeza quanto a configuração de um componente de cada vez. Isso resulta em uma “intercalação” das funções de limpeza e configuração.
Utilização
Injetar os estilos dinâmicos em bibliotecas CSS-em-JS
Tradicionalmente, você estilizaria componentes React usando CSS simples.
// Em seu arquivo JS:
<button className="success" />
// Em seu arquivo CSS:
.success { color: green; }
Algumas equipes preferem criar estilos diretamente no código JavaScript em vez de escrever arquivos CSS. Isso geralmente requer o uso de uma biblioteca CSS-em-JS ou de alguma ferramenta. Existem três abordagens comuns para CSS-em-JS:
- A extração estática para os arquivos CSS por um compilador
- Estilos em linha, por exemplo,
<div style={{ opacity: 1 }}>
- Injeção em tempo de execução de tags
<style>
Se utilizar CSS-em-JS, é recomendável uma combinação das duas primeiras abordagens (arquivos CSS para estilos estáticos, e estilos inline para estilos dinâmicos). Não recomendamos a injeção de tag em tempo de execução <style>
por duas razões:
- A injeção em tempo de execução obriga o navegador a recalcular os estilos com muito mais frequência.
- A injeção em tempo de execução pode ser muito lenta se ocorrer no tempo errado no ciclo de vida do React.
O primeiro problema não tem solução, mas o useInsertionEffect
pode ajudar a resolver o segundo problema.
Chame useInsertionEffect
para inserir os estilos antes que quaisquer efeitos de layout sejam acionados:
// Dentro da sua biblioteca CSS-em-JS
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
// Como explicado anteriormente, nós não recomendamos injeção em tempo de execução de tags <style>.
// Porém, se precisar ser feito, é importante que seja feito em useInsertionEffect.
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
}
function Button() {
const className = useCSS('...');
return <div className={className} />;
}
Da mesma forma que useEffect
, useInsertionEffect
não é executado no servidor. Caso seja necessário coletar as regras CSS que foram utilizadas no servidor, isso pode ser feito durante a renderização:
let collectedRulesSet = new Set();
function useCSS(rule) {
if (typeof window === 'undefined') {
collectedRulesSet.add(rule);
}
useInsertionEffect(() => {
// ...
});
return rule;
}
Deep Dive
Caso insira estilos durante a renderização e o React esteja a executar uma atualização não bloqueante, o navegador irá recalcular os estilos a cada frame enquanto renderiza uma estrutura de componentes, o que pode ser extremamente lento.
O useInsertionEffect
é melhor do do que inserir estilos durante o useLayoutEffect
ou useEffect
porque ele garante que no momento em que outros efeitos forem executados em seus componentes, as tags <style>
já estarão inseridas. Caso contrário, os cálculos de layout em Effects comuns estariam errados devido a estilos desatualizados