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); }); } }
Advertisement
Answer
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
.
P.S. 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, } }