J'essaie de trouver le meilleur moyen de supprimer un élément d'un tableau dans l'état d'un composant. Comme je ne devrais pas modifier directement la variable this.state
, existe-t-il un meilleur moyen (plus concis) de supprimer un élément d'un tableau que ce que j'ai ici ?:
onRemovePerson: function(index) {
this.setState(prevState => { // pass callback in setState to avoid race condition
let newData = prevState.data.slice() //copy array from prevState
newData.splice(index, 1) // remove element
return {data: newData} // update state
})
},
Je vous remercie.
mis à jour
Cela a été mis à jour pour utiliser le rappel dans setState. Cela devrait être fait lors de la référence à l'état actuel lors de sa mise à jour.
La façon la plus propre de faire ce que j'ai vu est avec filter
:
removeItem(index) {
this.setState({
data: this.state.data.filter((_, i) => i !== index)
});
}
Vous pouvez utiliser l'auxiliaire d'aide à l'immutabilité update()
DE _react-addons-update
, qui fait la même chose sous le capot, mais ce que vous faites est bien.
_this.setState(prevState => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
_
Je crois que le référencement de this.state
à l'intérieur de setState()
est déconseillé ( les mises à jour d'état peuvent être asynchrones ).
Les docs recommandent d'utiliser setState()
avec une fonction de rappel afin que prevState soit transmis au moment de l'exécution lorsque la mise à jour se produit. Donc, voici à quoi cela ressemblerait:
Utilisation de Array.prototype.filter sans ES6
removeItem : function(index) {
this.setState(function(prevState){
return { data : prevState.data.filter(function(val, i) {
return i !== index;
})};
});
}
Utilisation de Array.prototype.filter avec les fonctions de flèche ES6
removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i !== index)
}));
}
Utilisation de immutability-helper
import update from 'immutability-helper'
...
removeItem(index) {
this.setState((prevState) => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
}
Utilisation de Spread
function removeItem(index) {
this.setState((prevState) => ({
data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
}))
}
Notez que dans chaque instance, quelle que soit la technique utilisée, this.setState()
reçoit un rappel, et non une référence d'objet à l'ancien this.state
;
Voici un moyen de supprimer l'élément du tableau dans l'état à l'aide de la syntaxe d'étalement ES6.
onRemovePerson: (index) => {
const data = this.state.data;
this.setState({
data: [...data.slice(0,index), ...data.slice(index+1)]
});
}
Je veux parler ici même si cette question a déjà été répondu correctement par @pscl au cas où quelqu'un d'autre rencontrerait le même problème que moi. Parmi les 4 méthodes, j'ai choisi d'utiliser la syntaxe es6 avec les fonctions de flèche en raison de sa concision et de son manque de dépendance vis-à-vis des bibliothèques externes:
Utilisation de Array.prototype.filter avec les fonctions de flèche ES6
removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i != index)
}));
}
Comme vous pouvez le constater, j'ai légèrement modifié le type d'index (!==
à !=
) car, dans mon cas, je récupérais l'index dans un champ de chaîne.
Un autre point utile si vous observez un comportement étrange lors de la suppression d'un élément côté client est de NE JAMAIS utiliser l'index d'un tableau comme clé de l'élément :
// bad
{content.map((content, index) =>
<p key={index}>{content.Content}</p>
)}
Lorsque React diffère avec le DOM virtuel lors d'une modification, il examinera les clés pour déterminer ce qui a changé. Donc, si vous utilisez des index et qu'il y en a un de moins dans le tableau, le dernier sera supprimé. À la place, utilisez les identifiants du contenu comme clés, comme ceci.
// good
{content.map(content =>
<p key={content.id}>{content.Content}</p>
)}
Ce qui précède est un extrait de cette réponse d'un article connexe .
Bon codage à tous!
Comme mentionné dans un commentaire sur la réponse de ephrion ci-dessus, filter () peut être lent, en particulier avec les grands tableaux, car il effectue une boucle pour rechercher un index qui semble avoir déjà été déterminé. C'est une solution propre mais inefficace.
En guise d'alternative, vous pouvez simplement "découper" l'élément souhaité et concaténer les fragments.
var dummyArray = [];
this.setState({data: dummyArray.concat(this.state.data.slice(0, index), this.state.data.slice(index))})
J'espère que cela t'aides!
Vous pouvez utiliser cette fonction si vous souhaitez supprimer l'élément (sans index)
removeItem(item) {
this.setState(prevState => {
data: prevState.data.filter(i => i !== item)
});
}
Vous pouvez rendre le code plus lisible avec une fonction d'assistance à une ligne:
const removeElement = (arr, i) => [...arr.slice(0, i), ...arr.slice(i+1)];
puis utilisez-le comme ceci:
this.setState(state => ({ places: removeElement(state.places, index) }));