Estou escrevendo um script que move a lista suspensa abaixo ou acima da entrada, dependendo da altura da lista suspensa e da posição da entrada na tela. Também quero definir modificador para suspenso de acordo com sua direção. Mas usandosetState
dentro do componentDidUpdate
cria um loop infinito (o que é óbvio)
Eu encontrei uma solução ao usar getDOMNode
e definir o nome da classe para o menu suspenso diretamente, mas acho que deve haver uma solução melhor usando as ferramentas React. Alguém pode me ajudar?
Aqui está uma parte do código de trabalho com getDOMNode
(uma lógica de posicionamento um pouco negligenciada para simplificar o código)
let SearchDropdown = React.createClass({
componentDidUpdate(params) {
let el = this.getDOMNode();
el.classList.remove('dropDown-top');
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
el.classList.add('dropDown-top');
}
},
render() {
let dataFeed = this.props.dataFeed;
return (
<DropDown >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
e aqui está o código com setstate (que cria um loop infinito)
let SearchDropdown = React.createClass({
getInitialState() {
return {
top: false
};
},
componentDidUpdate(params) {
let el = this.getDOMNode();
if (this.state.top) {
this.setState({top: false});
}
if(needToMoveOnTop(el)) {
el.top = newTopValue;
el.right = newRightValue;
if (!this.state.top) {
this.setState({top: true});
}
}
},
render() {
let dataFeed = this.props.dataFeed;
let class = cx({'dropDown-top' : this.state.top});
return (
<DropDown className={class} >
{dataFeed.map((data, i) => {
return (<DropDownRow key={response.symbol} data={data}/>);
})}
</DropDown>
);
}
});
javascript
reactjs
ecmascript-6
Katerina Pavlenko
fonte
fonte
setState
vai sempre provocar uma re-render. Em vez de verificarstate.top
e ligarsetState
várias vezes, basta rastrear o que você desejastate.top
fazer em uma variável local e, uma vez no final dacomponentDidUpdate
chamada,setState
apenas se sua variável local não corresponderstate.top
. Como está agora, você redefine imediatamentestate.top
após a primeira re-renderização, o que o coloca no loop infinito.componentDidUpdate
no presente violino .componentShouldUpdate
?Respostas:
Você pode usar
setState
dentrocomponentDidUpdate
. O problema é que, de alguma forma, você está criando um loop infinito porque não há condição de interrupção.Com base no fato de que você precisa de valores fornecidos pelo navegador depois que o componente é renderizado, acho que sua abordagem sobre o uso
componentDidUpdate
está correta, ele só precisa de um tratamento melhor da condição que aciona osetState
.fonte
componentDidUpdate
e pode ser adicionada conforme necessáriorender
.A
componentDidUpdate
assinatura évoid::componentDidUpdate(previousProps, previousState)
. Com isso, você poderá testar quais objetos / estado estão sujos e chamarsetState
acordo.Exemplo:
fonte
componentDidMount
não possui argumentos e é chamado apenas quando o componente é criado; portanto, não pode ser usado para a finalidade descrita.componentDidMount
, então, quando escrevi a resposta, o famoso nome caiu em cascata.componentDidUpdate(prevProps, prevState) { if ( prevState.x!== this.state.x) { //Do Something } }
Se você usar
setState
dentrocomponentDidUpdate
dele, atualiza o componente, resultando em uma chamada para acomponentDidUpdate
qual, posteriormente, chamasetState
novamente, resultando no loop infinito. Você deve ligar condicionalmentesetState
e garantir que a condição que viola a chamada ocorra eventualmente, por exemplo:Caso você esteja atualizando apenas o componente enviando props para ele (ele não está sendo atualizado pelo setState, exceto pelo caso inside componentDidUpdate), você pode chamar
setState
inside emcomponentWillReceiveProps
vez decomponentDidUpdate
.fonte
getDerivedStateFromProps
.Este exemplo ajudará você a entender os ganchos do ciclo de vida do React .
Você pode
setState
nogetDerivedStateFromProps
método iestatic
acionar o método após a troca de objetoscomponentDidUpdate
.Em
componentDidUpdate
você receberá o terceiro parâmetro que retorna degetSnapshotBeforeUpdate
.Você pode verificar este link codesandbox
fonte
Eu diria que você precisa verificar se o estado já tem o mesmo valor que você está tentando definir. Se for o mesmo, não há motivo para definir o estado novamente para o mesmo valor.
Certifique-se de definir seu estado assim:
fonte
Eu tive um problema semelhante em que tenho que centralizar a dica de ferramenta. Reagir setState em componentDidUpdate me colocou em loop infinito, tentei condição funcionou. Mas descobri que o uso no retorno de chamada ref me deu uma solução mais simples e limpa; se você usar a função em linha para o retorno de chamada ref, enfrentará o problema nulo em cada atualização de componente. Portanto, use a referência de função no retorno de chamada ref e defina o estado lá, o que iniciará a nova renderização
fonte