Реагировать setState для многоуровневого объекта состояния - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь обновить свой объект состояния, который содержит несколько уровней. Посмотрите этот пример https://codesandbox.io/s/oq9kp9vy5y.

Проблема в том, что значения в методе рендеринга не обновляются ... только первое. Можно ли принудительно обновить или есть лучший способ?

Спасибо Kasper

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Попробуйте:

  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 голосов
/ 18 января 2019

В исходном состоянии у вас есть kitchen объект внутри calculatedUsage объекта.Но в вашем setState вызове у вас есть kitchen объект вне из calculatedUsage.

Кроме того, когда вы получаете доступ к предыдущему состоянию в setState, лучше всегоиспользуйте функциональную версию setState, например:

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

Причина этого заключается в том, что setState может быть асинхронным, что означает, что доступ к this.state внутри него может не дать ожидаемого значения,Использование функциональной версии для изменений состояния транзакции гарантирует стабильные результаты.

Вы также можете взглянуть на библиотеку immer .Это значительно упрощает обновление глубоко вложенного состояния, позволяя выполнять неизменяемые обновления с изменяемым API.Вот пример вашего кода codeandbox, который использует immer: https://codesandbox.io/s/180p7p0o84

0 голосов
/ 18 января 2019

Попробуйте что-то вроде этого

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);
...