React 的 setState()
或 useState()
的 Setter,其實都不是立即更新 State,因此直接從 State 取值,並不是最好的做法。
Version
macOS Mojave 10.14.6
WebStorm 2019.2.3
Node 12.11.0
Yarn 1.19.0
create-react-app 3.1.2
React 16.10.1
Class Component
錯誤寫法
App.js
import React, { Component } from 'react';
export default class extends Component {
state = {
count: 0,
};
addCount = () => {
this.setState({
count: this.state.count + 1
});
};
render() {
return (
<div>
<button onClick={ this.addCount }>+</button>
<div>{ this.state.count }</div>
</div>
);
}
}
export default App;
第 8 行
addCount = () => {
this.setState({
count: this.state.count + 1
});
};
其實 setState()
並不會立即更新 state,所以直接使用 side effect 從 this.state
不一定會抓到正確值。
正確寫法
App.js
import React, { Component } from 'react';
export default class extends Component {
state = {
count: 0,
};
addCount = () => {
this.setState(prevState => ({
count: prevState.count + 1
}));
};
render() {
return (
<div>
<button onClick={ this.addCount }>+</button>
<div>{ this.state.count }</div>
</div>
);
}
}
第 8 行
addCount = () => {
this.setState(prevState => ({
count: prevState.count + 1
}));
}
正確寫法應該在 setState()
使用沒有 side effect 的 pure function 為 callback,其 prevState
才會傳回更新後正確值。
Function Component
錯誤寫法
App.js
import React, { useState } from 'react';
export default () => {
let [count, setCount] = useState(0);
let addCount = () => setCount(count + 1);
return (
<div>
<button onClick={ addCount }>+</button>
<div>{ count }</div>
</div>
);
};
第 6 行
let addCount = () => setCount(count + 1);
其實 setCount()
並不會立即更新 state,所以直接使用 side effect 從 count
不一定會抓到正確值。
正確寫法
App.js
import React, { useState } from 'react';
export default () => {
let [count, setCount] = useState(0);
let addCount = () => setCount(prevCount => prevCount + 1);
return (
<div>
<button onClick={ addCount }>+</button>
<div>{ count }</div>
</div>
);
};
export default App;
第 6 行
let addCount = () => setCount(prevCount => prevCount + 1);
正確寫法應該在 setCount()
setter 使用沒有 side effect 的 callback,其 prevCount
argument 才會傳回更新後正確值。
Conclusion
- Class component 的
setState()
傳回的是state
object;而 function component 的 setter 傳回的是state
variable - 無論是 class component 的
setState()
,或者是 function component 的 setter,其 API 都是使用 callback 來表現 state 不會立即修改,而是修改後傳回正確值,語意甚佳