Eu tenho um aplicativo no qual preciso definir a altura de um elemento (digamos "conteúdo do aplicativo") dinamicamente. Ele pega a altura do "cromo" do aplicativo e o subtrai e define a altura do "conteúdo do aplicativo" para caber 100% dentro dessas restrições. Isso é super simples com exibições vanilla JS, jQuery ou Backbone, mas estou lutando para descobrir qual seria o processo certo para fazer isso no React?
Abaixo está um exemplo de componente. Eu quero poder definir app-content
a altura de 100% da janela menos o tamanho de ActionBar
e BalanceBar
, mas como sei quando tudo é renderizado e onde eu colocaria o material de cálculo nesta classe de reação?
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
javascript
reactjs
Oscar Godson
fonte
fonte
Respostas:
componentDidMount ()
Este método é chamado uma vez depois que seu componente é renderizado. Portanto, seu código ficaria assim.
fonte
componentDidUpdate
se os valores puderem mudar após a primeira renderização.componentDidMount()
não causa uma transição.componentDidMount: () => { setTimeout(addClassFunction())}
, ou use rAF, a resposta abaixo fornece essa resposta.Uma desvantagem de usar
componentDidUpdate
, oucomponentDidMount
é que eles são realmente executados antes que os elementos dom sejam desenhados, mas depois de terem passado do React para o DOM do navegador.Diga, por exemplo, se você precisou definir node.scrollHeight como node.scrollTop renderizado, os elementos DOM do React podem não ser suficientes. Você precisa esperar até que os elementos sejam pintados para obter sua altura.
Solução:
Use
requestAnimationFrame
para garantir que seu código seja executado após a pintura do seu objeto recém-renderizadofonte
_this.getDOMNode is not a function
que diabos é esse código?Na minha experiência,
window.requestAnimationFrame
não foi suficiente para garantir que o DOM foi totalmente renderizado / reflow-completecomponentDidMount
. Eu tenho um código em execução que acessa o DOM imediatamente após umacomponentDidMount
chamada e o uso exclusivowindow.requestAnimationFrame
resultaria na presença do elemento no DOM; no entanto, as atualizações nas dimensões do elemento ainda não são refletidas, pois ainda não ocorreu uma reflow.A única maneira verdadeiramente confiável para isso funcionar foi agrupar meu método em a
setTimeout
e awindow.requestAnimationFrame
para garantir que a pilha de chamadas atual do React seja limpa antes de se registrar para a renderização do próximo quadro.Se eu tivesse que especular por que isso está ocorrendo / necessário, eu poderia ver React em lotes de atualizações do DOM e não aplicar as alterações no DOM até que a pilha atual estivesse concluída.
Por fim, se você estiver usando medidas DOM no código que está disparando após os retornos de chamada React, provavelmente desejará usar esse método.
fonte
Apenas para atualizar um pouco esta questão com os novos métodos Hook, você pode simplesmente usar o
useEffect
hook:Além disso, se você deseja executar antes da pintura do layout, use o
useLayoutEffect
gancho:fonte
Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
eu vou editar.Você pode alterar o estado e, em seguida, fazer seus cálculos no retorno de chamada setState . De acordo com a documentação do React, isso é "garantido para disparar após a atualização ter sido aplicada".
Isso deve ser feito em
componentDidMount
ou em outro local do código (como em um manipulador de eventos de redimensionamento) e não no construtor.Essa é uma boa alternativa
window.requestAnimationFrame
e não possui os problemas que alguns usuários mencionaram aqui (precisando combiná-losetTimeout
ou chamá-lo várias vezes). Por exemplo:fonte
Sinto que esta solução está suja, mas aqui vamos nós:
Agora vou sentar aqui e esperar pelos votos negativos.
fonte
O React possui poucos métodos de ciclo de vida que ajudam nessas situações, incluindo as listas, entre outros, getInitialState, getDefaultProps, componentWillMount, componentDidMount etc.
No seu caso e nos casos que precisam interagir com os elementos DOM, é necessário aguardar até que o dom esteja pronto; portanto, use componentDidMount como abaixo:
Também para obter mais informações sobre o ciclo de vida em react, você pode consultar o link abaixo: https://facebook.github.io/react/docs/state-and-lifecycle.html
fonte
Eu tive o mesmo problema.
Na maioria dos cenários usando o hack-ish
setTimeout(() => { }, 0)
nocomponentDidMount()
funcionou.Mas não em um caso especial; e eu não queria usar o,
ReachDOM findDOMNode
pois a documentação diz:(Fonte: findDOMNode )
Então, nesse componente em particular, eu tive que usar o
componentDidUpdate()
evento, então meu código acabou sendo assim:E depois:
Finalmente, no meu caso, tive que remover o ouvinte criado em
componentDidMount
:fonte
Após a renderização, você pode especificar a altura como abaixo e a altura dos componentes de reação correspondentes.
ou você pode especificar a altura de cada componente de reação usando sass. Especifique os 2 primeiros div principais do componente de reação com largura fixa e, em seguida, a altura do div principal do componente com auto. Portanto, com base no conteúdo da terceira div, a altura será atribuída.
fonte
Na verdade, estou tendo problemas com um comportamento semelhante; renderizo um elemento de vídeo em um Component com o atributo id, portanto, quando RenderDOM.render () termina, ele carrega um plug-in que precisa do id para encontrar o espaço reservado e não consegue encontrá-lo.
O setTimeout com 0ms dentro do componentDidMount () o corrigiu :)
fonte
Na documentação ReactDOM.render () :
fonte
ReactDOM.render
, não para o de nível de componenteReactElement.render
(que é o assunto aqui).Para mim, nenhuma combinação
window.requestAnimationFrame
ousetTimeout
produziu resultados consistentes. Às vezes funcionava, mas nem sempre - ou às vezes seria tarde demais.Corrigi-o repetindo
window.requestAnimationFrame
as vezes necessárias.(Normalmente 0 ou 2-3 vezes)
A chave é
diff > 0
: aqui podemos garantir exatamente quando a página é atualizada.fonte
Eu tive uma situação estranha quando preciso imprimir um componente de reação que receba grande quantidade de dados e pinte na tela. Eu tentei todas as abordagens mencionadas, nenhuma delas funcionou de maneira confiável para mim, com requestAnimationFrame dentro de setTimeout, recebo tela vazia em 20% do tempo, então fiz o seguinte:
Basicamente, fiz uma cadeia de requestAnimationFrame, não tenho certeza se essa é uma boa ideia ou não, mas isso funciona em 100% dos casos para mim até agora (estou usando 30 como valor para a variável n).
fonte
Na verdade, existe uma versão muito mais simples e mais limpa do que o uso de request animationframe ou timeouts. Estou surpreso que ninguém o tenha trazido à tona: o gerenciador de onload de vanilla-js. Se você puder, use o component mount, caso contrário, simplesmente vincule uma função no campo onload do componente jsx. Se você deseja que a função execute todas as renderizações, execute-a também antes de retornar os resultados na função de renderização. o código ficaria assim:
}
fonte
Um pouco de atualização com
ES6
classes em vez deReact.createClass
Além disso - verifique os métodos de ciclo de vida do componente React: O ciclo de vida do componente
Cada componente tem muitos métodos semelhantes aos do
componentDidMount
eg.componentWillUnmount()
- o componente está prestes a ser removido do DOM do navegadorfonte