Aktualisieren eines Objekts mit setState in React

Ist es überhaupt möglich, Objekt's Eigenschaften mit setState zu aktualisieren?

Etwa so:

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

Ich habe es versucht:

this.setState({jasper.name: 'someOtherName'});

und dies:

this.setState({jasper: {name: 'someothername'}})

Das erste führt zu einem Syntaxfehler und das zweite bewirkt einfach nichts. Irgendwelche Ideen?

Lösung

Es gibt mehrere Möglichkeiten, dies zu tun, da die Zustandsaktualisierung eine asynchrone Operation ist. Um das Zustandsobjekt zu aktualisieren, müssen wir die Updater-Funktion mit "setState" verwenden.

1- Die einfachste Variante:

Erstelle zuerst eine Kopie von jasper und führe dann die Änderungen in dieser Kopie durch:

this.setState(prevState => {
  let jasper = Object.assign({}, prevState.jasper);  // creating copy of state variable jasper
  jasper.name = 'someothername';                     // update the name property, assign a new value                 
  return { jasper };                                 // return new object jasper object
})

Anstatt Object.assign zu verwenden, können wir es auch so schreiben:

let jasper = { ...prevState.jasper };

2- Verwendung des [Spreizungsoperators]3:

this.setState(prevState => ({
    jasper: {                   // object that we want to update
        ...prevState.jasper,    // keep all other key-value pairs
        name: 'something'       // update the value of specific key
    }
}))

Hinweis: Object.assign und Spread Operator erzeugen nur eine oberflächliche Kopie, wenn Sie also ein verschachteltes Objekt oder ein Array von Objekten definiert haben, benötigen Sie einen anderen Ansatz.


Aktualisieren eines verschachtelten Zustandsobjekts:

Angenommen, Sie haben state als definiert:

this.state = {
  food: {
    sandwich: {
      capsicum: true,
      crackers: true,
      mayonnaise: true
    },
    pizza: {
      jalapeno: true,
      extraCheese: false
    }
  }
}

Um extraCheese des Pizza-Objekts zu aktualisieren:

this.setState(prevState => ({
  food: {
    ...prevState.food,           // copy all other key-value pairs of food object
    pizza: {                     // specific object of food object
      ...prevState.food.pizza,   // copy all pizza key-value pairs
      extraCheese: true          // update value of specific key
    }
  }
}))

Array von Objekten aktualisieren:

Nehmen wir an, Sie haben eine ToDo-App, und Sie verwalten die Daten in diesem Formular:

this.state = {
  todoItems: [
    {
      name: 'Learn React Basics',
      status: 'pending'
    }, {
      name: 'Check Codebase',
      status: 'pending'
    }
  ]
}

Um den Status eines ToDo-Objekts zu aktualisieren, führen Sie eine Map auf dem Array aus und prüfen Sie auf einen eindeutigen Wert für jedes Objekt. Im Falle von condition=true geben Sie das neue Objekt mit dem aktualisierten Wert zurück, andernfalls dasselbe Objekt.

let key = 2;
this.setState(prevState => ({

  todoItems: prevState.todoItems.map(
    el => el.key === key? { ...el, status: 'done' }: el
  )

}))

Vorschlag: Wenn das Objekt keinen eindeutigen Wert hat, verwenden Sie den Array-Index.

Kommentare (11)

Im ersten Fall handelt es sich tatsächlich um einen Syntaxfehler.

Da ich den Rest Ihrer Komponente nicht sehen kann, ist es schwer zu erkennen, warum Sie hier Objekte in Ihrem Zustand verschachteln. Es ist keine gute Idee, Objekte im Komponentenzustand zu verschachteln. Versuchen Sie, Ihren Ausgangszustand zu setzen:

this.state = {
  name: 'jasper',
  age: 28
}

So können Sie, wenn Sie den Namen aktualisieren wollen, einfach aufrufen:

this.setState({
  name: 'Sean'
});

Erreicht man damit das, was man anstrebt?

Für größere, komplexere Datenspeicher würde ich etwas wie Redux verwenden. Aber das ist viel fortgeschrittener.

Die allgemeine Regel mit Komponente Zustand ist es nur zu verwenden, um UI-Status der Komponente zu verwalten (z. B. aktiv, Timer, etc.)

Schauen Sie sich diese Referenzen an:

Kommentare (2)

Eine andere Möglichkeit: Definieren Sie Ihre Variable aus dem Jasper-Objekt heraus und rufen Sie dann einfach eine Variable auf.

Spread-Operator: ES6

this.state = {  jasper: { name: 'jasper', age: 28 } } 

let foo = "something that needs to be saved into state" 

this.setState(prevState => ({
    jasper: {
        ...jasper.entity,
        foo
    }
})
Kommentare (1)