将嵌套对象/数组变为React中的状态?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (230)

我正在使用看起来像这样的React组件(我使用的组件的简化版本,如下所示)。

我的问题是:如何使用this.setState进行相同的操作?下面的代码工作,但我直接改变状态,我收到以下警告:

不要直接改变国家。使用setState()

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      playerState: [
        {
          name: 'Jack',
          hp: 30
        },{
          name: 'Alan',
          hp: 28
        }
      ],
    };
  }
  lowerPlayerHealth = (index) => () => {
    this.state.playerState[index].hp = this.state.playerState[index].hp - 1
    this.forceUpdate();
  }
  render() {
    return (
      <div className="App">
        <p>Player 1: {this.state.playerState[0].name}</p>
        <p>Health: {this.state.playerState[0].hp}</p>
        <button onClick={this.lowerPlayerHealth(0)}>Hit player 1</button>
        <p>Player 2: {this.state.playerState[1].name}</p>
        <p>Health: {this.state.playerState[1].hp}</p>
        <button onClick={this.lowerPlayerHealth(1)}>Hit player 2</button>
      </div>
    );
  }
}

渲染时,它看起来像这样:

提问于
用户回答回答于

如果要修改状态中的现有值,则不应直接从状态获取值并更新状态对象,而应使用updater函数,setState以便保证状态值是您当时需要的值。更新国家。这就是React的状态如何工作,这是一个非常常见的React错误。

来自官方文档

setState()并不总是立即更新组件。它可以批量推迟更新或推迟更新。这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。相反,使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发。如果需要根据以前的状态设置状态,请阅读下面的updater参数。 除非shouldComponentUpdate()返回false,否则setState()将始终导致重新呈现。如果正在使用可变对象且无法在shouldComponentUpdate()中实现条件呈现逻辑,则仅当新状态与先前状态不同时调用setState()将避免不必要的重新呈现。 第一个参数是带有签名的更新程序函数: (state, props) => stateChange state是对应用更改时组件状态的引用。它不应该直接变异。相反,应该通过基于state和props的输入构建新对象来表示更改。 更新程序功能接收的状态和道具都保证是最新的。updater的输出与state轻微合并。

所以你必须:

  • 在您想要更新组件时准确获取值。

要降低在州中找到的值:

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      playerState: [
        {
          name: 'Jack',
          hp: 30
        }, {
          name: 'Alan',
          hp: 28
        }
      ],
      };
  }

  lowerPlayerHealth = (index) => () => {
    this.setState((state, props) => {
      state.playerState[index].hp -=1; //update the current value found in state
      return (state); // update state ensuring the current values
    });
  }

  render() {
    return (
      <div className="App">
        <p>Player 1: {this.state.playerState[0].name}</p>
        <p>Health: {this.state.playerState[0].hp}</p>
        <button onClick={this.lowerPlayerHealth(0)}>Hit player 1</button>
        <p>Player 2: {this.state.playerState[1].name}</p>
        <p>Health: {this.state.playerState[1].hp}</p>
        <button onClick={this.lowerPlayerHealth(1)}>Hit player 2</button>
      </div>
      );
  }
}
用户回答回答于

你已经回答了自己的问题:不要改变状态。例如:

lowerPlayerHealth = (index) => () => {
  this.setState({
    playerState: {
      this.state.playerState,
      [index]: {
        ...this.state.playerState[index],
        hp: this.state.playerState[index].hp - 1
      }
    }
  };
}

扫码关注云+社区

领取腾讯云代金券