缺点直接改变状态和forceUpdate()vs setState

时间:2017-11-11 11:47:33

标签: javascript reactjs

React docs说Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable...但是当我根本不使用setState()时,这是一个非问题。

我能想到的唯一缺点是:

  • 无法使用shouldComponentUpdate / componentWillUpdate / componentDidUpdate来比较旧州和新州。

  • 对于其他人来说,可能会使维护更加困难。因为它不是标准的做事方式。

但是没有使用setState()和直接改变状态的其他缺点吗?

编辑:我已经删除了我的理由,为什么我会被这个想法所吸引。我知道这是一种反模式,我知道它可能不是最好的方法。但这个问题都是关于"为什么"。

EDIT2:此处的关键字是other

中的... are there any other disadvantages ...

1 个答案:

答案 0 :(得分:5)

你不应该直接改变状态。 setState的异步性质有办法解决它。 setState提供了您可以使用的callback

此外,forceUpdate完全绕过了shouldComponentUpdate,这不是一个好的模式,尤其是在使用React.PureComponent进行道具的浅层比较时。

此外,您不应该使用反模式,而是尝试按照文档建议的正确方式解决您的问题

  

使用setState的另一个好处就是你可以放松一下   模式是为了比较您的previouscurrentState   使对象mutable特别在您的生命周期函数中

     

直接的缺陷设置状态是React的生命周期   方法 - shouldComponentUpdate()componentWillUpdate(),   componentDidUpdate() - 依赖于调用的状态转换   setState()。如果您直接更改状态并使用,请致电setState()   如果是空对象,则无法再实现这些方法。

此外,您可能知道您的代码与React交互的方式是这些覆盖或其他问题不会发生,但您正在创建一种情况,其他开发人员或未来的更新可能会突然发现自己奇怪或当他们开始遵循正确的方法时出现微妙的问题

使用setState来改变状态

class App extends React.Component {
  state =  {
      counter: 0
  }
  updateCounter = () => {
    this.setState(prevState => ({counter: prevState.counter + 1}));
  }
  componentWillUpdate(nextProps, nextState){
    console.log(this.state.counter === nextState.counter);
  }
  
  componentDidUpdate(prevProps, prevState) {
     console.log(this.state.counter === prevState.counter);
  }
  render() {
      return (
        <div>
          {this.state.counter}
          <button onClick={this.updateCounter}>Increment</button>
        </div>
      )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

直接改变状态

class App extends React.Component {
  state =  {
      counter: 0
  }
  updateCounter = () => {
    this.state.counter =  this.state.counter + 1;
    this.forceUpdate();
  }
  componentWillUpdate(nextProps, nextState){
    console.log(this.state.counter === nextState.counter);
  }
  
  componentDidUpdate(prevProps, prevState) {
     console.log(this.state.counter === prevState.counter);
  }
  render() {
      return (
        <div>
          {this.state.counter}
          <button onClick={this.updateCounter}>Increment</button>
        </div>
      )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>