鍍金池/ 問答/HTML/ React setStats數(shù)組不更新,百思不得其解。

React setStats數(shù)組不更新,百思不得其解。

樓樓今日遇到個坑爹的問題。
就是 this.setStats({}) 對 this.stats 不更新問題
問題是這樣的
constructor(props) {

    super(props);
    this.state = {
        imageList: []
    }

    WechatService.getMaterialOrealList("image").then((result) => {
        this.setState({
            imageList: result
        })
    });

}

 async handleInputChangeUpload(event) {
    var target = event.target;
    var file = target.files[0];

    var formData = new FormData();
    formData.append('file', file);

    var result = await WechatService.updateMaterialImage(formData);

    var lists = this.state.imageList;
    lists.push(result);
    console.log(lists);
    //同步更新
    this.setState((prevState, props) => ({
        imageList: lists
    }))

}

圖片描述
數(shù)組的長度已經(jīng)變成了11可是 render 并沒有更新??!,這是為什么呢?
此方法已經(jīng)是谷歌出來的東西,可是好像并沒有成功
this.setState((prevState, props) => ({

       imageList: lists
   }))

但是樓主看了一下elementsUI 的代碼后進行一次修改后,發(fā)現(xiàn)一下方案倒是成功了。百思不得其解,不知道那位小兄弟可以解答一下。
constructor(props) {

   super(props);
   this.state = {
   //這是把數(shù)組用一個對象包含起來
       data: {
           imageList: []
       }
   }

}

componentWillMount() {

   WechatService.getMaterialOrealList("image").then((result) => {
       this.setState({
           data: Object.assign({}, {
               imageList: result
           })
       })
   });

}

handleUpload() {

   this.refs.inputFile.click();

}

async handleInputChangeUpload(event) {

   var target = event.target;
   var file = target.files[0];

   var formData = new FormData();
   formData.append('file', file);

   var result = await WechatService.updateMaterialImage(formData);

   var lists = this.state.data.imageList;
   lists.push(result);
   this.setState((prevState, props) => ({
   //淺拷貝、對象屬性的合并
       data: Object.assign({}, { imageList: lists })
   }))

   setTimeout(() => {
       console.log(this.state.data);
   });

}
這樣使用對象進行修改的數(shù)組變量反而更新了。
圖片描述
這是為什么呢?
無法解答

作者:傻夢獸
鏈接:https://juejin.im/post/5b1a22...
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

回答
編輯回答
司令

樓上的回答有一點缺陷。

白天我看到這個問題也是這么想的,可是setStaterender并沒有自帶的shallow compare,猜想不成立。剛才自己試了一下,即使是空的setState也可以觸發(fā)當(dāng)前組件re-render。

至于題目中出現(xiàn)的情況,我猜測有fetch的容器組件跟列表項展示組件是分開的,同時展示組件使用了PureComponent或者在ShouldComponentUpdate中做了shallow compare,或者是其他的節(jié)流方案。總之對于不改變地址的imageList數(shù)組而言,是無法觸發(fā)展示組件的re-render的。

樓上回答的缺陷在于,如果不使用節(jié)流方案,那么React本身不會進行任何shallow compare,所有的變動都是基于最終得出的Vitural DOM diff來進行的,用來對比的不是imageList本身,而是每一個由imageList map出來的item。即若能觸發(fā)展示組件的re-render,即使不改變數(shù)組的引用,依然可以正確顯示變動

2017年11月9日 13:32
編輯回答
歆久
var lists = this.state.imageList;
lists.push(result);
console.log(lists);
//同步更新
this.setState((prevState, props) => ({
    imageList: lists
}));

有一個點你要弄清楚,在js中,數(shù)組的賦值是引用傳遞的,list.push相當(dāng)于直接改變了數(shù)組對應(yīng)的內(nèi)存塊,這樣修改,react內(nèi)部用來做對比的imageList也被你改了,因為都是指向同一塊內(nèi)存。最后re-render的時候,react發(fā)現(xiàn)你的imageList是一樣的,好的,沒有變化,不更新了。

你可以這么做:

// 使用新的數(shù)組
var lists = [...this.state.imageList];
// 其他語句不變
2017年4月12日 16:07