React状态为何不再不可变?React16.02中可手动修改状态的疑问
嘿,这个问题挺有代表性的!我来帮你拆解一下背后的原因~
首先得澄清一个误区:React从来没有完全禁止手动修改this.state,但它从设计上就强烈不推荐这么做。你现在看到的“生效”其实是特定场景下的巧合,而非React16突然允许了这种操作。
具体来说,有这几个关键点:
React的状态更新逻辑核心:
setState的作用不只是修改state,更重要的是通知React“组件状态变了,需要重新渲染UI”。而直接修改this.state只是改变了对象的值,但不会触发重新渲染。但如果之后你碰巧触发了组件的重新渲染(比如父组件更新、调用了setState修改其他状态、或者触发了props变化),那修改后的state就会被同步到UI上——这就是你看到“生效”的原因。React16的细节变化:在React16初期(比如你用的16.0.2),开发模式下的状态突变警告可能还没像后续版本那样严格,或者你没注意到控制台的警告。但核心机制和之前是一致的:手动修改state本身不会触发渲染,只是后续的渲染让修改被展示了出来。
为什么绝对不能这么做:哪怕看起来生效了,手动修改
this.state都是糟糕的实践:- 破坏了React的单向数据流,组件状态变得不可预测,后期排查bug会非常头疼
- 开发模式下React会逐步加强对这类操作的警告,甚至在某些场景下直接报错
- 可能导致UI和实际state不同步,出现诡异的渲染问题
举个简单的例子,你就能明白:
class Counter extends React.Component { state = { count: 0 }; badHandleClick = () => { // 手动修改state,此时UI不会立刻更新 this.state.count += 1; // 但如果之后调用setState触发渲染,修改后的count就会显示出来 this.setState({}); }; render() { return <button onClick={this.badHandleClick}>{this.state.count}</button>; } }
总结一下:你遇到的情况并不是React16允许了手动更新state,而是你修改state后,刚好有其他操作触发了组件重新渲染,才让修改后的状态显示在了UI上。无论哪个React版本,都应该始终用setState(类组件)或者useState的更新函数(函数组件)来修改状态,这才是符合React设计规范的做法。
内容的提问来源于stack exchange,提问作者Alexander Knyazev

