React: Manipulando DOM em componentDidUpdate

Criado em 23 set. 2016  ·  3Comentários  ·  Fonte: facebook/react

Olá, isso é mais como uma pergunta, gostaria de abrir uma discussão sobre a manipulação do DOM em componentDidUpdate .

Estou criando um plugin React. Ele tem que fazer alguns cálculos DOM, porque CSS não é poderoso o suficiente para cobrir tudo que este plugin precisa fazer. O problema é que preciso ajustar algumas propriedades CSS, dependendo do valor de retorno de getBoundingClientRect () de algum outro elemento DOM renderizado pelo mesmo componente .

Então, tecnicamente, temos 3 opções:

1) Calcule getBoundingClientRect em componentDidUpdate e chamando setState com os valores calculados. Tenho medo do loop infinito que pode acontecer em certos casos, então não optaria por este.

2) Faça como em 1) e brinque um pouco com shouldComponentUpdate , mas isso parece muito complexo e ilegível. Muitas perguntas surgem que dependem de um determinado caso de uso.

3) Atualize o DOM do componentDidUpdate. Esta é a solução que decidi buscar, funciona, é simples, estável e funciona como planejado. No entanto, sinto que estou no limite, então gostaria de verificar se essa é uma maneira OK de fazer as coisas. Posso manipular o DOM em componentDidUpdate ? É chamado toda vez que render é concluído, e não há problema em descartar minhas alterações, porque nos próximos render modificarei o DOM novamente.

Aqui está uma parte do código

componentDidMount() {
  this.recalculateIndent();
}

componentDidUpdate() {
  this.recalculateIndent();
}

recalculateIndent() {
  // calculate indent based on getBoundingClientRect of some DOM reference
  this.textareaRef.style.textIndent = `${indent}px`;
}

render() {
   return (
   ...
   <textarea ref={ref => this.textareaRef = ref}/>
   ...
   );
}

Comentários muito úteis

@jvorcak usando componentDidUpdate é o lugar correto para manipular o DOM manualmente após uma renderização. De acordo com os documentos:

Use isso como uma oportunidade para operar no DOM quando o componente for atualizado.

Além disso, tentamos usar o rastreador de problemas apenas para solicitações de recursos e relatórios de erros. As perguntas de uso devem ser direcionadas a outro lugar, como discuss.reactjs.org ou StackOverflow. Obrigado!

Todos 3 comentários

Cada solução (método do ciclo de vida do componente) é adequada para a situação concreta, mas a manipulação do DOM está errada. Use o estado e o componente de renderização novamente. Exemplo para meu último caso de uso "cabeçalho fixo para tabela + rolagem virtual para o corpo da tabela", espero que isso ajude você a entender o fluxo correto.

  1. Construtor do componente: valor do estado inicial: bodyHeight = 0 (ou nulo, como você quiser).
  2. Primeiro renderiza, renderiza o cabeçalho da tabela, mas o corpo da tabela vazio (0 linhas).
  3. componentDidMount - leia o cabeçalho e a altura do DOM do contêiner (+ algum cálculo ...) e setState para bodyHeight (re-renderizar).
  4. Segunda renderização, bodyHeight! == 0, o corpo da tabela será renderizado. Agora, o parâmetro de altura é conhecido ( posso defini-lo usando o componente prop "style", em vez da manipulação DOM ), posso adicionar componentes para linhas.
  5. Ouvinte de evento adicional para "redimensionar" (redimensionar documento / navegador), adicionar componentDidMount, remover em componentWillUnmount. No manipulador de eventos, faço a mesma coisa como em componentDidMount - leio novos valores de altura DOM e setState.
  6. Não há manipulação de DOM manualmente, o react faz o trabalho.

@jvorcak usando componentDidUpdate é o lugar correto para manipular o DOM manualmente após uma renderização. De acordo com os documentos:

Use isso como uma oportunidade para operar no DOM quando o componente for atualizado.

Além disso, tentamos usar o rastreador de problemas apenas para solicitações de recursos e relatórios de erros. As perguntas de uso devem ser direcionadas a outro lugar, como discuss.reactjs.org ou StackOverflow. Obrigado!

E se você quiser atualizar um componente após alterar algo em outro?

Esta página foi útil?
0 / 5 - 0 avaliações