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 ...
答案 0 :(得分:5)
你不应该直接改变状态。 setState的异步性质有办法解决它。 setState
提供了您可以使用的callback
。
此外,forceUpdate完全绕过了shouldComponentUpdate
,这不是一个好的模式,尤其是在使用React.PureComponent
进行道具的浅层比较时。
此外,您不应该使用反模式,而是尝试按照文档建议的正确方式解决您的问题
使用
setState
的另一个好处就是你可以放松一下 模式是为了比较您的previous
和currentState
使对象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>