在调用setState()之前直接改变状态是否可以?

时间:2017-09-16 06:16:36

标签: reactjs typescript

我使用轻量级ORM将我的反应应用程序与外部服务连接...此包返回模型的对象,并允许您直接对它们执行操作。虽然这真的很棒,但我很难弄清楚如何在state中包含这些对象,并且仍然遵循"永远不要直接修改状态"反应的承租人。

如果我有一个更新帐户名称的组件,是否可以接受这样的操作?

interface IAppState {
  account: Account
}

class App extends React.Component<{}, IAppState> {
  constructor(props) {
    super(props);
    this.state = {
      account: new Account()
    }
  }

  //set the new name and update the external service
  public updateAccount = (newName: string)=>{
    account.name = newName; //REDFLAG!!!
    acc.update().then(()=>{
        this.setState({ account: this.state.account })
    })
  }

  //retrieve our account object from external service
  public componentDidMount() {
    const qParams = queryString.parse(window.location.search);
    Account.get(qParams.externalId).then((acc)=>{
        this.setState({account: acc})
    })
  }

  render() {
    return <NameEditor handleClick={this.updateAccount} account={a} />
    }
 }

我想我可以通过启动一个空白的ORM对象,复制属性,发送更新然后设置状态来避免变异状态,但这似乎是一个很大的痛苦。特别是因为这些ORM对象可以包含子ORM对象我也希望能够修改。

我是否正在改变状态&#34;危险&#34;或者&#34;糟糕的形式&#34; ???

更新

做了一些阅读并且看起来肯定这可能是糟糕的形式,并且可能使用react/addons优雅地导航... 但是,如果ORM调用对对象有副作用?例如,调用insert设置对象外部id字段。

2 个答案:

答案 0 :(得分:3)

public updateAccount = (newName: string)=>{
    //account.name = newName; //REDFLAG!!!
    // You can use the below code to update name after it is updated
    // on server.
    // This will work because the object being passed here
    // will be merged with Component state.
    acc.update().then(()=>{
        this.setState({account: {name : newName}})
    })
}

不推荐直接修改状态,因为反应不会知道更改,也不会导致重新渲染。

所有差异都发生在Virtual DOM上,并且仅响应将更改属性更新到Browser DOM。您可以在此处详细了解react diffing algorithm

答案 1 :(得分:1)

React建议使用不可变对象来设置状态。您可以使用Object.assign或immutable.js来实现此目的,这将使我们的生活更轻松。 如果改变状态对象,它将影响反应组件的性能。

您可以参考以下链接获取更多信息。

https://facebook.github.io/react/docs/optimizing-performance.html#examples