為什么使用
setState()
由蘑?setState()
會(huì)對(duì)一個(gè)組件的state
對(duì)象安排一次更新尼酿。當(dāng)state
改變了裳擎,該組件就會(huì)重新渲染思币。開發(fā)中我們不能直接通過修改state
當(dāng)中的值來讓界面發(fā)生更新羡微,因?yàn)樾薷牧?state
后希望的是 React 根據(jù)最新的state
值來進(jìn)行更新界面惶我,但是這種方式 React 并不知道數(shù)據(jù)發(fā)生了變化,所以必須通過setState()
來告訴 React 數(shù)據(jù)已經(jīng)發(fā)生了變化需要更新界面盯蝴。
一捧挺、setState 可能是異步更新
class App extends Component {
constructor() {
super();
this.state = {
number: 0
}
}
render() {
return (
<div>
<h2>{this.state.number}</h2>
<button onClick={e => this.addText()}>+1</button>
</div>
)
}
addText() {
this.setState({
number: this.state.number + 1
});
console.log(this.state.number); // 0
}
}
當(dāng)調(diào)用 this.setState({ number: this.state.number + 1 })
后所打印得到的值依舊為 0尿瞭。
獲取異步更新后的數(shù)據(jù):
class App extends Component {
constructor() {
super();
this.state = {
number: 0
}
}
render() {
return (
<div>
<h2>{this.state.number}</h2>
<button onClick={e => this.addText()}>+1</button>
</div>
)
}
// 方式二:通過聲明周期函數(shù)獲取異步更新的值
componentDidUpdate() {
console.log(this.state.number); // 1
}
addText() {
this.setState({
number: this.state.number + 1
}, () => { // 方式一:通過 setState 的回調(diào)函數(shù)獲取異步更新的值
console.log(this.state.number); // 1
});
}
}
二筷厘、setState 可能是同步更新
- 當(dāng) setState() 方法在 setTimeout() 中執(zhí)行:
class App extends Component {
constructor() {
super();
this.state = {
number: 0
}
}
render() {
return (
<div>
<h2>{this.state.number}</h2>
<button onClick={e => this.addText()}>+1</button>
</div>
)
}
addText() {
setTimeout(() => {
this.setState({
number: this.state.number + 1
});
console.log(this.state.number); // 1
}, 0);
}
}
- 當(dāng) setState() 方法在原生 DOM 事件中執(zhí)行:
class App extends Component {
constructor() {
super();
this.state = {
number: 0
}
}
componentDidMount() {
// 原生點(diǎn)擊事件
const btnEl = document.getElementById('btn');
btnEl.addEventListener('click', () => {
this.setState({
number: this.state.number + 1
});
console.log(this.state.number); // 1
})
}
render() {
return (
<div>
<h2>{this.state.number}</h2>
<button id='btn'>+1</button>
</div>
)
}
}
一般情況下酥艳,
setState()
方法在組件生命周期或 React 合成事件中是異步更新的摊溶;在setTimeout()
或者原生 DOM 事件中是同步的。
三充石、setState 數(shù)據(jù)的合并
// this.state 當(dāng)中有兩個(gè)屬性
constructor() {
super();
this.state = {
number: 0,
name: 'zhangsan'
}
}
/* --------------- */
// 更新 state
this.setState({
number: 10
});
當(dāng) constructor
中的 this.state
有多個(gè)屬性時(shí)莫换,調(diào)用 this.setState()
方法更新其中一條 number
屬性后,不會(huì)將之前的 name
屬性覆蓋骤铃,而是單獨(dú)修改 number
屬性拉岁,等同于:
Object.assign({}, this.state, { number: 10 })
四、setState 本身的合并
class App extends Component {
constructor() {
super();
this.state = {
number: 0
}
}
render() {
return (
<div>
<h2>{this.state.number}</h2>
<button onClick={e => this.addText()}>+1</button>
</div>
)
}
addText() {
// setState 本身被合并
// this.setState({
// number: this.state.number + 1
// });
// this.setState({
// number: this.state.number + 1
// });
// this.setState({
// number: this.state.number + 1
// });
/* 最終結(jié)果還是 1 */
// setState 合并時(shí)進(jìn)行累加
this.setState((prevState, props) => {
return {
number: prevState.number + 1
}
})
this.setState((prevState, props) => {
return {
number: prevState.number + 1
}
})
this.setState((prevState, props) => {
return {
number: prevState.number + 1
}
})
/* 最終結(jié)果為 3 */
}
}