简体   繁体   中英

React setState does not update a state array value

I am trying to change the state in a class component by using setState .

More specific I have a table, and I want to edit/update one of its elements. For this case, I am passing the indeces to the handleTableFieldOnChange function for the position of the value in the array.

Since I know that I should not mutate the state, I used an external library to deep copy the tables array/list.

The deep copy and the new value assignment works. The deep copy worked also with the JSON.parse(JSON.stringify(this.state.tables)); alternative.

Problem: For some reason the this.setState(...) does not change the tables value.

I do know the setState is asynchronous, this is why I used the callback and within it, the console.log(...) to check the updated value.

console.log(...) still emits the old value.

private handleTableFieldOnChange(val: boolean | string | number | [number, string], tblRowIndex: number, tblIndex: number, tblColINdex: number) {
        const cloneDeep = require('lodash.clonedeep');
        const newTables = cloneDeep(this.state.tables);
        if (newTables && newTables[tblIndex] && newTables[tblIndex].items ) {
            newTables[tblIndex].items![tblRowIndex][tblColINdex].value = val;
        }
        this.setState( {tables: newTables}, () => {
            console.log(this.state.tables)
        })
    }



state: State = {
  tables: [],
  report: this.props.report,
};

constructor(props: DetailProp, state: State) {
  super(props, state);                                
  this.initFieldsAndTabels();
}

 private initFieldsAndTabels() {
        if (this.state.report && this.state.report.extraction_items) {
            this.state.tables = [];
            this.state.report.extraction_items.forEach((extractionItems) => {
                    this.state.tables.push(extractionItems);
            });
        }
    }

The code in handleTableFieldOnChange looks fine to me.

However in initFieldsAndTabels you are applying push on state directly instead of calling setState which may probably cause the issues:

this.state.report.extraction_items.forEach((extractionItems) => {
  this.state.tables.push(extractionItems); //#HERE
});

Also as React.Component docs state you should not call setState in constructor (you are calling initFieldsAndTabels in constructor . Instead you could use componentDidMount .

PS If you want to add those extraction items in the constructor then you need something like this:

  constructor(props) {
    super(props);
    // method should return a new array/object, but not modify state
    const tables = this.initFieldsAndTabels();
    this.state = {
      tables,
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM