it-swarm.com.de

Ersetzen Sie das Objekt im Array im Reaktienstatus

Diese Frage könnte ein wenig auf die Frage der "Best Practice" fallen, aber bitte haben Sie etwas Geduld.

Hier ist ein Teil meines Zustands:

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
        }...

Was ich tun muss, ist REPLACE das Objekt an einem bestimmten Index im Header-Array.

Ich weiß nicht, wie ich das mit der setState-Methode wie in this.setState(headers[1] = {obj}) mache - aber das ist offensichtlich ungültig. Meine derzeitige Methode besteht darin, ein neues Array zu erstellen und das alte wie folgt zu blockieren:

_updateStyle(props) {
  let newState = Object.assign({}, this.state)
  newState.typeElements.headers[props.index] = props
  this.setState(newState)
};

Für mein kleines, hackiges Projekt denke ich, dass es in Ordnung ist, aber ich finde, dass dies sehr schwerfällig ist und schnell zu Performanceproblemen in jeder Größenordnung führen würde.

7
motleydev

Aktualisiert: Da diese Antwort immer noch positiv bewertet wird, ist zu beachten, dass die vorstehende Antwort mit modernem JavaScript und React nicht mehr aktuell ist. Das "Update" -Admin ist jetzt veraltet und "Immutability-Helper" kann stattdessen verwendet werden.

Die React-Dokumente erwähnen auch, warum Unveränderlichkeit wichtig ist daher den mutierenden Zustand vermeiden. Für unveränderliche Updates können Sie Object.assign() oder spread syntax verwenden, die für jede Verschachtelungsebene ausgeführt werden muss, wie in diesem Beispiel das verschachtelte headers-Objekt und seine Array-Elemente. In diesem speziellen Beispiel können Sie den Array-Index als Schlüssel verwenden, sodass Sie mit dem Spread-Operator auch einen flachen Klon des Arrays erstellen und ein neues Objekt als Wert am angegebenen Index im geklonten Array zuweisen können.

_updateStyle (props) {
  const { typeElements } = this.state;
  const updatedHeaders = [...typeElements.headers];
  updatedHeaders[props.index] = props;
  this.setState({
    ...this.state,
    typeElements: {
      ...typeElements,
      headers: updatedHeaders
    }
  ));
}

Eine andere Lösung, für die keine Spread-Syntax erforderlich ist und die benötigt wird, wenn wir den Array-Index nicht verwenden, um das zu ersetzende Objekt zu finden, ist array.map, um ein neues Array zu erstellen und das neue Objekt anstelle des alten Objekts zurückzugeben Index.

  const updatedHeaders = typeElements.headers.map((obj, index) => {
    return index === props.index ? props : obj;
  });

Ähnliche Beispiele in den Redux-Dokumenten erklären auch "unveränderliche Aktualisierungsmuster" .

React hat dazu einige Unänderungshilfen, die in .__ erklärt werden. die Dokumente: https://facebook.github.io/react/docs/update.html

In Ihrem Fall könnten Sie den Befehl $ splice verwenden, um ein Element und .__ zu entfernen. Fügen Sie den neuen Index am angegebenen Index hinzu, zum Beispiel:

_updateStyle (props) {
  this.setState(update(this.state.typeElements, 
    { $splice: [[props.index, 1, props]] }
  ));
}
11
Robin Venneman

verwenden Sie Unveränderlichkeitshilfe

sie finden dort schöne Beispiele

1
ChaosPredictor

Bietet eine bessere Erklärung, wie dies zu erreichen ist.

  • Suchen Sie zunächst den Index des Elements, das Sie im Zustandsarray ersetzen.
  • Zweitens update das Element an diesem Index
  • Drittens rufen Sie setState mit der neuen Sammlung auf
import 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});
}
0
daino3

Ich habe deine Idee. Soweit ich weiß, kann die setState()-Methode den untergeordneten Inhalt des Arrays nicht ändern. Verwenden Sie diese Methode stattdessen, ändern Sie sie einfach direkt.

this.state.typeElements.headers[theIndex] = value;

durch direkte Änderung wird die Komponente jedoch nicht erneut gerendert. Sie können es erzwingen, mit dieser Methode erneut zu rendern.

this.forceUpdate()

hinweis: Aber seien Sie vorsichtig, diese Praxis wird als schlecht angesehen. Sie müssen sicherstellen, dass Ihr Zustand unveränderlich ist. Here unveränderliche Arrayreferenz

0

Object.Assign verwendet eine flache Kopie, keine tiefe Kopie. 

Bitte beachten Sie, dass Object.assign({}, this.state) in Ihrem Beispiel nur Links zu den nächsten untergeordneten Elementen der state kopiert, d. H. Zu typeElements, das headers-Array jedoch nicht kopiert wird.

Es gibt einen syntaktischen Zucker ... für Object.Assign in ES6, Babel hat das spezielle Addon transform-object-rest-spread

let newHeaders = { ...this.state.typeElements.headers};
newHeaders[index] = props.Something;

let newState = {...state, typeElements: { newHeaders }};
0
Artru