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 de qualquer efeito que precise 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 limpeza. -
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.
Devoluções
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
Normalmente, os componentes React são estilizados com 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 bloqueada, 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á estão inseridas. Caso contrário, os cálculos de layout em Effects comuns estariam errados devido a estilos desatualizados