Je veux ajouter un élément à la fin d'un tableau state
, est-ce la bonne façon de le faire?
this.state.arrayvar.Push(newelement);
this.setState({arrayvar:this.state.arrayvar});
Je crains que la modification du tableau sur place avec Push
puisse causer des problèmes - est-ce sûr?
L'alternative consistant à créer une copie du tableau et à setState
ing semble inutile.
Les documents React dit:
Traitez cet Etat comme s'il était immuable.
Votre Push
mutera l'état directement et cela pourrait potentiellement conduire à un code source d'erreurs, même si vous "réinitialisez" l'état ultérieurement. F.ex, certaines méthodes de cycle de vie telles que componentDidUpdate
ne se déclenchent pas.
L'approche recommandée dans les versions ultérieures de React consiste à utiliser une fonction Updater lors de la modification d'états afin d'éviter les conditions de concurrence:
this.setState(prevState => ({
arrayvar: [...prevState.arrayvar, newelement]
}))
La "perte" de mémoire n'est pas un problème comparé aux erreurs que vous pourriez rencontrer en utilisant des modifications d'état non standard.
Syntaxe alternative pour les versions précédentes de React
Vous pouvez utiliser concat
pour obtenir une syntaxe propre, car elle renvoie un nouveau tableau:
this.setState({
arrayvar: this.state.arrayvar.concat([newelement])
})
Dans ES6, vous pouvez utiliser l’opérateur Spread :
this.setState({
arrayvar: [...this.state.arrayvar, newelement]
})
Le plus facile, si vous utilisez ES6
.
initialArray = [1, 2, 3];
newArray = [ ...initialArray, 4 ]; // --> [1,2,3,4]
Le nouveau tableau sera [1,2,3,4]
mettre à jour votre état dans React
this.setState({arrayvar:[...this.state.arrayvar, newelement]});
La manière la plus simple avec ES6
:
this.setState(prevState => ({
array: [...prevState.array, newElement]
}))
React peut effectuer des mises à jour par lots, et la bonne approche consiste donc à fournir à setState une fonction qui effectue la mise à jour.
Pour le complément de mise à jour de React, ce qui suit fonctionnera de manière fiable:
this.setState( (state) => update(state, {array: {$Push: [4]}}) );
ou pour concat ():
this.setState( (state) => {
state.array = state.array.concat([4]);
return state;
});
Ce qui suit montre ce que https://jsbin.com/mofekakuqi/7/edit?js,output comme exemple de ce qui se passe si vous vous trompez.
L'invocation setTimeout () ajoute correctement trois éléments car React ne met pas à jour par lots les mises à jour dans un rappel setTimeout (voir https://groups.google.com/d/msg/reactjs/G6pljvpTGX0/0ihYw2zK9dEJ ).
Le buggy onClick ajoutera seulement "Troisième", mais celui corrigé ajoutera F, S et T comme prévu.
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
array: []
}
setTimeout(this.addSome, 500);
}
addSome = () => {
this.setState(
update(this.state, {array: {$Push: ["First"]}}));
this.setState(
update(this.state, {array: {$Push: ["Second"]}}));
this.setState(
update(this.state, {array: {$Push: ["Third"]}}));
};
addSomeFixed = () => {
this.setState( (state) =>
update(state, {array: {$Push: ["F"]}}));
this.setState( (state) =>
update(state, {array: {$Push: ["S"]}}));
this.setState( (state) =>
update(state, {array: {$Push: ["T"]}}));
};
render() {
const list = this.state.array.map((item, i) => {
return <li key={i}>{item}</li>
});
console.log(this.state);
return (
<div className='list'>
<button onClick={this.addSome}>add three</button>
<button onClick={this.addSomeFixed}>add three (fixed)</button>
<ul>
{list}
</ul>
</div>
);
}
};
ReactDOM.render(<List />, document.getElementById('app'));
Comme @nilgun mentionné dans le commentaire, vous pouvez utiliser les aides réagir immutabilité J'ai trouvé cela très utile.
De la docs:
Simple Push
var initialArray = [1, 2, 3];
var newArray = update(initialArray, {$Push: [4]}); // => [1, 2, 3, 4]
(initialArray est toujours [1, 2, 3].} _
Vous pouvez utiliser cette méthode : [tableau destructuring]
this.setState(prevState => {
return {
arrayData: [...prevState.arrayData, newElement]
}
});
Réagissez avec la documentation: ne modifiez jamais cet état directement. Comme David Hellsing a expliqué dans sa réponse : appeler ensuite setState () peut remplacer la mutation que vous avez effectuée. Traitez cet état comme s'il était immuable.
this.setState({
arrayvar: [...this.state.arrayvar, ...newelement]
})