Cette question pourrait tomber un peu du côté d'une question de "meilleure pratique", mais s'il vous plaît, continuez avec moi.
Voici une partie de mon état:
this.state = {
typeElements: {
headers: [
{
name: "h1",
size: 70,
lineHeight: 1.25,
kearning: 0,
marginAfter: 0
}, {
name: "h2",
size: 70,
lineHeight: 1.25,
kearning: 0,
marginAfter: 0
}, {
name: "h3",
size: 70,
lineHeight: 1.25,
kearning: 0,
marginAfter: 0
}...
Ce que je dois faire est de remplacer l'objet à un index donné sur le tableau d'en-têtes.
Je ne sais pas comment faire cela avec la méthode setState comme dans this.setState(headers[1] = {obj})
- mais c'est évidemment invalide. Ma méthode actuelle consiste à créer un nouveau tableau et à supprimer l'ancien comme ceci:
_updateStyle(props) {
let newState = Object.assign({}, this.state)
newState.typeElements.headers[props.index] = props
this.setState(newState)
};
Pour mon petit projet de hacky, je suppose que tout va bien, mais j’ai l’impression que ce projet est très lourd et que cela entraînerait rapidement des problèmes de performances à n’importe quel niveau.
Mise à jour: comme cette réponse reçoit toujours des votes positifs, sachez que la réponse précédente ci-dessous est obsolète avec JavaScript moderne et React. L'addon "update" est maintenant hérité et "immutability-helper" peut être utilisé à la place.
Les documents React expliquent également pourquoi l’immutabilité est importante , évitez donc les mutations. Pour les mises à jour immuables, vous pouvez utiliser la syntaxe Object.assign()
ou spread qui doit être effectuée pour chaque niveau d'imbrication, comme dans cet exemple, l'objet imbriqué headers
et ses éléments de tableau. Dans cet exemple particulier, nous pouvons utiliser l'index de tableau comme clé afin de pouvoir également utiliser l'opérateur spread pour créer un clone superficiel du tableau et affecter un nouvel objet comme valeur à un index donné dans le tableau cloné.
_updateStyle (props) {
const { typeElements } = this.state;
const updatedHeaders = [...typeElements.headers];
updatedHeaders[props.index] = props;
this.setState({
...this.state,
typeElements: {
...typeElements,
headers: updatedHeaders
}
));
}
Une autre solution qui ne nécessite pas la syntaxe de propagation et qui est nécessaire si nous n’utilisons pas l’index de tableau pour trouver l’objet à remplacer, utilise array.map
pour créer un nouveau tableau et renvoie le nouvel objet à la place de l’ancien. indice.
const updatedHeaders = typeElements.headers.map((obj, index) => {
return index === props.index ? props : obj;
});
Des exemples similaires dans la documentation Redux expliquent également "modèles de mise à jour immuables" .
React a quelques aides d’immuabilité pour cela, ce qui est expliqué dans les docs: https://facebook.github.io/react/docs/update.html
Dans votre cas, vous pouvez utiliser la commande $ splice pour supprimer un élément et ajoutez le nouveau à l'index donné, par exemple:
_updateStyle (props) { this.setState(update(this.state.typeElements, { $splice: [[props.index, 1, props]] } )); }
utiliser immutability-helper
vous pouvez y trouver de beaux exemples
Offrant une meilleure explication sur la façon de procéder.
update
l'élément à cet indexsetState
avec la nouvelle collectionimport update from 'immutability-helper';
// this.state = { employees: [{id: 1, name: 'Obama'}, {id: 2, name: 'Trump'}] }
updateEmployee(employee) {
const index = this.state.employees.findIndex((emp) => emp.id === employee.id);
const updatedEmployees = update(this.state.employees, {$splice: [[index, 1, employee]]}); // array.splice(start, deleteCount, item1)
this.setState({employees: updatedEmployees});
}
J'ai eu ton idée. Autant que je sache, la méthode setState()
ne peut pas changer le contenu enfant du tableau. Alors utilisez plutôt cette méthode, modifiez-la directement.
this.state.typeElements.headers[theIndex] = value;
mais, en le modifiant directement, le composant ne sera pas rendu de nouveau. Vous pouvez le forcer à effectuer un nouveau rendu avec cette méthode.
this.forceUpdate()
remarque: mais attention, cette pratique est considérée comme mauvaise, vous devez vous assurer que votre état est immuable. Ici référence de tableau immuable
Object.Assign utilise une copie superficielle, pas une copie complète.
Sachez que, dans votre exemple, Object.assign({}, this.state)
copie uniquement les liens vers les enfants les plus proches du tableau state
, c’est-à-dire typeElements
, mais le tableau headers
n’est pas copié.
Il y a un sucre syntaxique ...
dans ES6 pour Object.Assign, Babel a l'addon spécial transform-object-rest-spread .
let newHeaders = { ...this.state.typeElements.headers};
newHeaders[index] = props.Something;
let newState = {...state, typeElements: { newHeaders }};