J'ai un composant parent qui rend certains composants enfants. Le composant enfant doit afficher les informations transmises par le composant parent.
Un jeu de cuirassé multijoueur:
Le composant parent contient un champ de 10 x 10 à 10 x 30 boutons (composants enfants). Si un bouton est enfoncé, un signal avec la position du bouton est émis vers l'API. L'API décide si le bouton enfoncé doit changer sa couleur.
En mettant à jour l'état du parent, les accessoires des composants enfants ne seront pas mis à jour si l'enfant est créé dynamiquement.
Pas possible dans mon cas
Je considère l'enfant comme un composant de vidage / présentation car il n'affiche que des informations. Dans mon cas également, il y a entre 100 et 300 composants enfants. Redux et React
Il y a entre 100 et 300 composants enfants ... Ne pas abuser des références
Que devrais-je faire? Existe-t-il une solution qui n'est pas anti-modèle?
Code actuel
class Parent extends React.Component {
constructor(props) {
super(props);
this.state={
foo: 'BAR'
}
this.child=undefined;
}
componentWillMount(){
this.child=<Child foo={this.state.foo}/>
}
componentDidMount(){
var that=this
setTimeout(function(){
that.setState({ //it is just here for demonstration
foo: 'FOO'
})
}, 1000);
}
render() {
return (
<div>
Is: {this.child}
Not Dynamic created: <Child foo={this.state.foo}/>
Actual: <p>{this.state.foo}</p>
</div>
);
}
}
class Child extends React.Component {
render() {
return (
<p>{this.props.foo}</p>
);
}
}
ReactDOM.render(<Parent />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Code avec l'approche de @RaghavGarg et @Clinton Blackburn
class Parent extends React.Component {
constructor(props) {
super(props);
this.state={
foo: 'BAR'
}
this.child=undefined;
}
componentDidMount(){
var that=this
setTimeout(function(){
that.setState({ //it is just here for demonstration
foo: 'FOO'
})
}, 1000);
}
renderChild(){
return <Child foo={this.state.foo} />
}
render() {
const child=this.renderChild()
return (
<div>
Is: {child}
Not Dynamic created: <Child foo={this.state.foo}/>
Actual: <p>{this.state.foo}</p>
</div>
);
}
}
class Child extends React.Component {
render() {
return (
<p>{this.props.foo}</p>
);
}
}
ReactDOM.render(<Parent />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>
Comme @Clinton l'a dit, componentWillMount
ne serait appelé qu'une seule fois. Donc, vous lancez essentiellement votre this.child
variable, mais ne mettez à jour que l'état, vous devez également mettre à jour la valeur de la variable.
Puisque vous créez simplement vos composants dynamiques et que vous les enregistrez dans l'instance de classe (comme this.child
). Je vous recommande de faire la même tâche dans componentWillUpdate
. Ainsi, chaque fois que votre état change, il sera reflété dans vos variables dépendantes. Mais assurez-vous de ne pas utiliser setState
cette méthode de cycle de vie.
componentWillUpdate()
est appelée juste avant le rendu lorsque de nouveaux accessoires ou état sont reçus. Utilisez cette opportunité pour effectuer une préparation avant qu'une mise à jour ne se produise.
Envisagez également d'utiliser le constructeur pour initier l'état et de ne pas l'utiliser setState
dans componentWillMount
.
componentWillMount()
est appelé juste avant le montage. Il est appelé avantrender()
, donc un appelsetState()
synchrone dans cette méthode ne déclenchera pas de rendu supplémentaire. En règle générale, nous vous recommandons d'utiliserconstructor()
plutôt le pour initialiser l'état.
Référence:
https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
Alors maintenant, je suppose que vous aurez un DS (peut-être un objet ou un tableau imbriqué) dans l'état dans lequel vous maintiendrez le statut de chaque boîte (composant enfant). Vous pouvez faire une boucle dessus et fournir un unique key
(peut-être comme {row}-{col}
) à chacun d'eux, il vous suffit maintenant de mettre à jour l'état afin de refléter le changement dans l'enfant spécifique.
Remarque: l' utilisation de la clé unique pour chaque enfant permettra à react d'optimiser en interne le nouveau rendu et ne rendra pas l'enfant (en utilisant une clé unique), ce qui n'est pas modifié. Voir le code ci-dessous pour référence.
this.state = {
boxes: {
1: {
1:{ status: true, /* more data */ },
2:{ status: true, /* more data */ },
},
2: {
1:{ status: true, /* more data */ },
2:{ status: true, /* more data */ },
},
3: {
1:{ status: true, /* more data */ },
2:{ status: true, /* more data */ },
},
4: {
1:{ status: true, /* more data */ },
2:{ status: true, /* more data */ },
}
}
};
// this will create a 4x2 box, now you will render using above object
// ...somewhere in your render method
{
Object.keys(this.state.boxes).map(row => (
<div key={`row-${row}`} className="row">
{
Object.keys(this.state.boxes[row]).map(column => (
<Child
key={`box-${row}x${column}`}
data={this.state.boxes[row][column]}
/>
))
}
</div>
))
}
Désormais, chaque fois que vous changez la case status
of say 2x1
en false
, react ne restituera que l'enfant avec la clé box-2x1
.
shouldComponentUpdate
doit être utilisé pour décider si vous souhaitez mettre à jour le composant lorsque l'état change. C'est une méthode de cycle de vie du composant React. Par défaut, il retourne true
, mais vous pouvez revenir en false
fonction de votre condition pour ne pas mettre à jour le composant. Cela aiderait certainement à maintenir les bonnes performances.
Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.
En cas d'infraction, veuillez [email protected] Supprimer.
laisse moi dire quelques mots