this.state.Arr.splice(...)
this.setState({
Arr:this.state.Arr
})
複製代碼
這樣雖然能夠生效,但應該遵循immutable的原則而儘可能避免直接修改state中的數據,能夠改成javascript
const Arr = [...this.state.Arr]
Arr.splice(...)
this.setState({
Arr
})
複製代碼
先來看一個例子,console.log打印的結果分別是什麼java
this.state = {
num: 0,
}
componentWillMount() {
this.setState({
num: this.state.num + 1,
});
console.log(this.state.num);
this.setState({
num: this.state.num + 1,
});
console.log(this.state.num);
}
render() {
console.log(this.state.num);
}
複製代碼
是否是認爲會是: 1 2 2,可是打印出來的是0 0 1。瀏覽器
再來一個簡單的例子。bash
// 錯誤
this.setState({
counter: this.state.counter + this.props.increment
})
複製代碼
咱們會發現,以上代碼可能致使 counter(計數器) 更新失敗。綜上可知,state(狀態) 更新多是異步的,React.js 爲了優化性能,有可能會將多個 setState() 調用合併爲一次更新。異步
由於 this.props 和 this.state 多是異步更新的,因此你不能依賴他們的值計算下一個state(狀態)。函數
咱們先經過一張圖瞭解一下它的隊列機制。性能
setState方法經過一個隊列機制實現state更新,當執行setState的時候,會將須要更新的state合併以後放入狀態隊列,而不會當即更新this.state(能夠和瀏覽器的事件隊列類比)優化
如何解決state(狀態) 異步更新的問題,從而拿到正確的數據呢。ui
setTimeout(() => {
this.setState({
num: this.state.num + 1,
});
console.log(this.state.num); // 1
this.setState({
num: this.state.num + 1,
});
console.log(this.state.num); // 2
}, 0);
複製代碼
// 例1的異步處理。setState自己還能夠接收第二個參數,解決setState更新完後拿到數據觸發,因此第二個參數是一個回調函數
this.setState(((prevState) => {
prevState.num++;
}), () => {
// 拿到數據後能夠作更新視圖等等操做
console.log(this.state.num); // 2
});
this.setState(((prevState) => {
prevState.num++;
}), () => {
console.log(this.state.num); // 2
});
// 例2的異步處理,第一個參數是原始state,等同於this.state,第二個參數是父組件傳遞的屬性
this.setState((prevState, props) => ({
//prevState:在改變state中的數據以前,打印出當前的state
counter: prevState.counter + props.increment
}))
複製代碼
setStatePromise(cb) {
return new Promise(((resolve, reject) => {
this.setState(cb, resolve);
}));
}
this.setStatePromise(() => {
return ({
dataArray: [1, 2, 3, 4],
total: 10
})
}).then(() => {
console.log(this.state.dataArray); //[1, 2, 3, 4]
});
複製代碼
上面咱們進行了屢次的setState,可是實際上組件只會從新渲染一次,而不是屢次;這是由於在 React.js 內部會把 JavaScript 事件循環中的消息隊列的同一個消息中的 setState 都進行合併之後再從新渲染組件。所以,在使用 React.js 的時候,並不須要擔憂屢次進行 setState 會帶來性能問題。this