Ich versuche, mein Statusobjekt zu aktualisieren, das mehrere Ebenen enthält. Siehe dieses Beispiel https://codesandbox.io/s/oq9kp9vy5y.

Das Problem ist, dass die Werte in der Rendermethode nicht aktualisiert werden ... nur der erste. Kann ich ein Update erzwingen oder gibt es einen besseren Weg?

Danke Kasper

3
Kasper Gantzhorn 18 Jän. 2019 im 21:59

3 Antworten

Beste Antwort

In Ihrem Ausgangszustand befindet sich das Objekt kitchen innerhalb des Objekts calculatedUsage. Bei Ihrem setState -Aufruf befindet sich das kitchen -Objekt außerhalb von calculatedUsage.

Wenn Sie innerhalb von setState auf den vorherigen Status zugreifen, verwenden Sie am besten die Funktionsversion von setState, z.

componentDidMount() {
  this.setState(
    prevState => ({
      caclulatedUsage: {
        ...prevState.caclulatedUsage,
        bath: 12,
        kitchen: {
          ...prevState.caclulatedUsage.kitchen,
          stove: 14,
          fridge: 23,
          dishwasher: 34
        }
      }
    }),
    () => {
      console.log(this.state);
    }
  );
}

Der Grund dafür ist, dass setState asynchron sein kann, was bedeutet, dass der Zugriff auf this.state darin möglicherweise nicht den erwarteten Wert ergibt. Die Verwendung der Funktionsversion für Änderungen des Transaktionsstatus garantiert konsistente Ergebnisse.

Vielleicht möchten Sie auch einen Blick in die immer Bibliothek werfen. Dies erleichtert das Aktualisieren eines tief verschachtelten Status erheblich, da Sie unveränderliche Aktualisierungen mit einer veränderlichen API durchführen können. Hier ist eine Abzweigung Ihres Codesandbox-Beispiels, das immer verwendet: https://codesandbox.io/s/180p7p0o84

3
Shane Cavaliere 18 Jän. 2019 im 19:44

Versuchen Sie so etwas

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      caclulatedUsage: {
        bath: 0,
        kitchen: {
          stove: 0,
          fridge: 0,
          dishwasher: 0
        },
        livingroom: {
          tv: 0,
          tvBox: 0
        }
      }
    };
  }

  componentDidMount() {
    this.setState(
      {
        caclulatedUsage: Object.assign({}, this.state.access, {
          caclulatedUsage: {
            ...this.state.caclulatedUsage,
            bath: 12
          },
          kitchen: {
            ...this.state.caclulatedUsage.kitchen,
            stove: 14,
            fridge: 23,
            dishwasher: 34
          }
        })
      },
      () => {
        console.log(this.state);
      }
    );
  }

  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        {this.state.caclulatedUsage.bath}
        <br />
        {this.state.caclulatedUsage.kitchen.stove}
        <br />
        {this.state.caclulatedUsage.kitchen.fridge}
        <br />
        {this.state.caclulatedUsage.kitchen.dishwasher}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
1
TRomesh 18 Jän. 2019 im 19:11

Versuchen:

  componentDidMount() {
    this.setState(
      {
        caclulatedUsage: {
          ...this.state.caclulatedUsage,
          bath: 12,
           kitchen: {
               ...this.state.caclulatedUsage.kitchen,
               stove: 14,
               fridge: 23,
               dishwasher: 34
           }
        }

      }
      () => {
        console.log(this.state);
      }
    );
  }
0
SomoKRoceS 18 Jän. 2019 im 19:13