setState() à l'intérieur de componentDidUpdate()
Je suis en train d'écrire un script qui se déplace déroulante ci-dessous ou au-dessus de l'entrée en fonction de la hauteur de de liste déroulante et la position de l'entrée sur l'écran. Aussi, je veux modificateur de liste déroulante en fonction de sa direction.
Mais à l'aide de setState
à l'intérieur de la componentDidUpdate
crée une boucle infinie(ce qui est évident)
J'ai trouvé une solution en utilisant getDOMNode
et configuration d'un nom de classe à déroulant directement, mais je pense qu'il devrait y avoir une meilleure solution à l'aide de Réagir outils. Quelqu'un peut-il m'aider?
Voici une partie du code du travail avec getDOMNode
(je
un peu négligés logique de positionnement pour simplifier le code)
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>
);
}
});
et voici le code avec setstate (ce qui crée une boucle infinie)
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>
);
}
});
- Je pense que le truc c'est que
setState
toujours déclencher un nouveau rendu. Plutôt que de vérifierstate.top
et de l'appel desetState
plusieurs fois, il suffit de suivre ce que vous voulezstate.top
à être dans une variable locale, puis une fois à la fin decomponentDidUpdate
appelsetState
seulement si votre variable locale ne correspond passtate.top
. Comme il est en ce moment, vous rétablir immédiatement lestate.top
après le premier rendu, qui vous met dans la boucle infinie. - Voir les deux implémentations différentes de
componentDidUpdate
dans ce violon. - damn it! variable locale résout tout le problème, comment n'avais-je pas pensé à elle par mysef! Merci!!!!
- si vous écrivez une réponse, je vais le marquer comme correct
- Je pense que vous devriez accepter la réponse ci-dessous. Si vous avez bien lu encore, je pense que vous trouverez cela répond à la question initiale suffisamment.
- Pourquoi personne n'a suggéré de passer de l'état dans
componentShouldUpdate
?
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser
setState
à l'intérieur decomponentDidUpdate
. Le problème, c'est que quelque part, vous créez une boucle infinie car il n'y a pas de condition d'arrêt.Basée sur le fait que vous avez besoin de valeurs qui sont fournies par le navigateur une fois que le composant est rendu, je pense que votre approche sur l'utilisation de
componentDidUpdate
est correcte, elle a simplement besoin d'une meilleure gestion de l'état qui déclenche lasetState
.componentDidUpdate
et peut tout simplement être ajoutés selon les besoins dansrender
à la place.Si vous utilisez
setState
à l'intérieur decomponentDidUpdate
il met à jour le composant, ce qui résulte en un appel àcomponentDidUpdate
qui, par la suite des appelssetState
résultant à nouveau dans la boucle infinie. Vous devriez conditionnellement appelsetState
et de s'assurer que la condition violation de l'appel se produit finalement.e.g:Dans le cas où vous ne sont que la mise à jour du composant par l'envoi d'accessoires pour elle(elle n'est pas mise à jour par setState, sauf pour le cas à l'intérieur de componentDidUpdate), vous pouvez appeler
setState
à l'intérieur decomponentWillReceiveProps
au lieu decomponentDidUpdate
.La
componentDidUpdate
signature estvoid::componentDidUpdate(previousProps, previousState)
. Avec cela, vous serez en mesure de test accessoires/état sont sales et appelsetState
en conséquence.Exemple:
componentDidMount
n'ont pas d'arguments, et qui n'est appelée que lorsque le composant est créé, ne peut donc pas être utilisé pour l'objet.componentDidMount
, donc quand j'ai écrit la réponse que le nom célèbre cascade Encore une fois, Merci & Grand rattraper!componentDidUpdate(prevProps, prevState) { if ( prevState.x!== this.state.x) { //Do Something } }
Je dirais que vous devez vérifier si l'état a déjà la même valeur que vous essayez de définir. Si c'est la même chose, il n'y a pas de point pour définir l'état de nouveau pour la même valeur.
Assurez-vous de définir votre état comme ceci:
J'ai eu un problème similaire où je centre l'info-bulle. Réagir setState dans componentDidUpdate ne m'a mis dans une boucle infinie, j'ai essayé d'état, il a travaillé. Mais j'ai trouvé de l'aide dans la réf de rappel m'a donné plus simple et propre solution, si vous utilisez la fonction en ligne pour les ref de rappel vous sera le visage de l'null problème pour chaque composant de mise à jour. Donc, l'utilisation de la fonction de référence dans la réf de rappel et de l'ensemble de l'etat, qui va initier le re-rendre
Cet exemple clair de la Réagir Cycle de Vie des Crochets.
Vous pouvez
setState
dansgetDerivedStateFromProps
méthode c'est à direstatic
et de déclencher la méthode après les accessoires de changement danscomponentDidUpdate
.Dans
componentDidUpdate
vous obtiendrez 3ème param qui renvoie degetSnapshotBeforeUpdate
.JS:
HTML: