【问题标题】:React: can you use setState with existing state object?React:您可以将 setState 与现有状态对象一起使用吗?
【发布时间】:2016-07-22 14:03:48
【问题描述】:

假设我有一个包含 10 个字段的“状态”的 React 组件:

this.state = {
    field1: 1,
    field2: 2,
    ... other fields
    something: 'a'
};

在我的一个事件处理程序中,我决定要更新单个状态字段。这样做是否出于某种原因是不好的做法?

// state has 10 other properties not touched here, and I want them to
// retain their existing values
this.state.something = 'b';
this.setState(this.state);

或者我必须这样做:

this.setState({
    field1: this.state.field1,
    field2: this.state.field2,
    ... set other fields with current value
    something: 'b'
});

我知道有些库可以轻松复制对象状态,只是想知道是否有必要这样做。我还应该补充一点,我已经尝试过了,它似乎有效,但我没有看到任何在线示例这样做,所以想知道是否有什么原因不这样做。

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    要更新单个字段,您需要使用该字段传递对象。 React 会为你合并它。

    this.setState({something: 'b'})
    

    【讨论】:

    • 假设我想更新 10 个字段中的 3 个,这对我也有用并被合并吗?
    • 当然。 {field1: 1, field2: 2 ...}
    • 可以工作,但会导致编译器错误,除非State 被正确声明。
    【解决方案2】:

    永远不要直接改变 this.state,因为之后调用 setState() 可能 替换您所做的突变。把 this.state 当作是 不可变。

    使用Object.assign 克隆对象

    const newState = Object.assign({}, this.state, {
      something: 'b'
    })
    
    this.setState(newState)
    

    或者你可以合并当前状态:

    this.setState({
      something: 'a',
      something2: 'b', 
    })
    

    【讨论】:

    • 谢谢,正是我想要的。当我浏览文档时一定错过了。
    • 如果你错过了这些信息,你可以在这里阅读facebook.github.io/react/docs/component-api.html
    • 你的两个例子有不同的效果吗?在重新渲染方面?
    【解决方案3】:

    您实际上会将State 的所有成员标记为可选。

    interface State {
      field1?: number, 
      field2?: number,
    }
    

    这并不像您想象的那么不安全。 TypeScript 添加了新鲜度 的概念来支持这种模式和其他模式。

    更多

    这里有介绍:

    https://basarat.gitbooks.io/typescript/content/docs/types/freshness.html#use-case--react-state

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多