Comment éviter setState() à l'intérieur de render() lors de l'état dépend de rendu
J'ai une grille qui rend les cartes de variable hauteurs.
Pour obtenir la hauteur de la carte, j'ai rendu la carte enveloppé dans ReactHeight
(https://github.com/nkbt/react-height), ce qui me permet de passer d'une fonction de rappel lorsque la hauteur est prêt.
Je garde la carte des hauteurs dans un tableau dans le composant state
, qui-je mettre à jour étant donné que la carte des hauteurs signalés.
Lorsque toutes les tailles sont disponibles, j'ai calculer la marge sur les hauteurs, qui render
passe pour les cartes
Dans une version simplifiée, il ressemble à ceci.
class Grid extends Component {
constructor() {
...
this.state = { cardHeights: {}, paddings: [] }; //initial state
}
componentDidUpdate() {
const i = setInterval(() => {
if (all heights are ready) {
//...calculate paddings
this.setState(paddings: calculatedPaddings);
clearInterval(i);
}
}, 100);
//*A*
}
updateCardHeights(index, height) {
this.setState(prevState => ({
cardHeights: {
...prevState.cardHeights,
[index]: height,
},
}));
}
render() {
//index = cards are indexed like 1 2 3
// 4 5 6
// 7 8 9
// 10 11 12
// ...
return (
<ReactHeight onHeightReady={ height => this.updateCardHeights(index, height) }
<Card padding={this.state.paddings[index]}/>
</ReactHeight>
);
}
}
Je sais setState()
appels render
, et l'appel d'une fonction de la mutation de l'état à l'intérieur render
conduit généralement à une boucle infinie.
Dans mon code, render
appelle une fonction qui met à jour this.state.cardHeights
tableau, et le rendu de son enfant composant, Card
, indirectement dépend this.state.cardHeights
, depuis this.state.paddings
qu'il dépend directement de la est calculé sur la base cardHeights sur componentDidUpdate()
.
Cependant, je ne parviens pas à la hauteur de la Card
composant sans rendre, de sorte que la seule façon que je peux penser à est de faire padding
un prop
à la carte et de l'état du composant, et la modification de l'état après le rendu.
Ma question est:
-
En quelque sorte mon code ne se traduira pas par une boucle infinie, même si je vais changer d'état à l'intérieur de rendu, mais c'est une meilleure façon de le faire?
-
clearInterval()
à l'intérieur de moncomponentDidUpdate()
fonction ne semble pas fonctionner. J'ai mis une instruction print dans*A*
partie, et il garde l'impression, même lorsque la si la condition est remplie etclearInterval()
est censé être appelé. Cela peut-il être à cause de mon mauvais état de mutation?
- Quelle est la
index
ici? - peut-être que vous pouvez utiliser
shouldComponentUpdate(nextProps, nextState)
. Lire la suite ici: facebook.github.io/réagir/docs/...
Vous devez vous connecter pour publier un commentaire.
Dans de tels cas, vous devez vérifier si la valeur précédente et la nouvelle valeur sont même avant la mise à jour de l'état. J'espère que votre taille n'est mis à jour pour chaque rendu. Vous pouvez donc avoir un chèque en
updateCardheights
afin de déterminer si il y a un changement réel et ensuite mettre à jour l'état. Cela garantit qu'il n'a pas les mises à jour de l'état pour les mises à jour. Mais si le rendu de votre état va être mise à jour, le problème restera le même.J'ai suivantes solution en ce qui concerne votre question ci-dessus.
Suffit d'attribuer le gestionnaire d'événement à l'extérieur de la fonction rendu. Et n'oubliez pas de lier votre gestionnaire d'événement à l'intérieur du constructeur. Après cela, vous pouvez appeler ce gestionnaire d'événement à l'intérieur de votre fonction rendu