一尘不染

实际上,为什么我不能直接修改组件的状态?

javascript

我知道,React教程和文档毫无疑问地警告说,状态不应该直接变异,所有事情都应该通过setState

我想了解一下,为什么我不能直接更改状态,然后(在同一函数中)调用this.setState({})仅触发render

例如:以下代码似乎正常工作:

const React = require('react');

const App = React.createClass({
    getInitialState: function() {
        return {
            some: {
                rather: {
                    deeply: {
                        embedded: {
                            stuff: 1
                        }}}}};
    },
    updateCounter: function () {
        this.state.some.rather.deeply.embedded.stuff++;
        this.setState({}); // just to trigger the render ...
    },
    render: function() {
        return (
                <div>
                Counter value: {this.state.some.rather.deeply.embedded.stuff}
                <br></br>
                <button onClick={this.updateCounter}>inc</button>
                </div>
        );
    }
});

export default App;

我全都遵循以下约定,但是我想进一步加深对ReactJS实际工作方式的理解,以及可能出现问题的地方或上述代码的最佳选择。

下的笔记this.setState文档基本上识别两个陷阱:

  1. 如果您直接更改状态,然后再调用this.setState它,则可能会替换(覆盖?)所做的更改。我看不到上面的代码中如何发生这种情况。
  2. setState可能会this.state以异步/延迟的方式有效地进行更改,因此this.state在调用后this.setState立即访问时,不能保证您访问最终的更改状态。我知道,如果this.setState更新函数的最后一次调用不是问题,

阅读 252

收藏
2020-04-25

共1个答案

一尘不染

React文档setState对此有这样的说法:

切勿this.state直接进行突变,因为setState()随后的呼叫可能会取代您所做的突变。对待this.state就好像它是不可变的。

setState()不会立即变异,this.state但会创建待处理的状态转换。this.state调用此方法后进行访问可能会返回现有值。

无法保证对呼叫的同步操作,setState并且可以为提高性能而对呼叫进行批量处理。

setState()除非在中实现了条件渲染逻辑,否则它将始终触发重新渲染shouldComponentUpdate()。如果正在使用可变对象,并且无法在中实现逻辑shouldComponentUpdate(),则setState()仅在新状态与先前状态不同时进行调用才能避免不必要的重新渲染。

基本上,如果this.state直接进行修改,则会造成一种情况,即这些修改可能会被覆盖。

与您的扩展问题1)和2)有关,setState()不是立即的。
它根据其正在进行的状态对状态转换进行排队,该状态转换可能不包括对的直接更改this.state。由于已排队而不是立即应用,因此完全有可能在两者之间进行某些修改,以使您的直接更改被覆盖。

如果没有别的,您可能会觉得更好,只是考虑将不直接修改this.state视为良好做法。您可能个人知道您的代码与React交互时不会发生这些覆盖或其他问题,但是您正在创建一种情况,其他开发人员或将来的更新可能突然发现自己遇到奇怪或微妙的问题。

2020-04-25