Reputation: 1046
Working on reactJS project, and I know we don't mutate the state (usually i don't but don't know the exact reason) so I just tried some wrong approach even its working correctly.
import logo from './logo.svg';
import './App.css';
import Test from './test';
import {Home, NotFoundComponent,Contact, Profile} from './test/home'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
list: [42, 33, 68],
};
}
onUpdateItem = i => {
this.state.list[i]++;
this.setState({
list: this.state.list,
})
// this.setState(state => {
// const list = state.list.map((item, j) => {
// if (j === i) {
// return item + 1;
// } else {
// return item;
// }
// });
// return {
// list,
// };
// });
};
render() {
return (
<div>
<ul>
{this.state.list.map((item, index) => (
<li key={item}>
The person is {item} years old.
<button
type="button"
onClick={() => this.onUpdateItem(index)}
>
Make me one year older
</button>
</li>
))}
</ul>
</div>
);
}
}
export default App;
this.state.list[i]++;
this.setState({
list: this.state.list,
})
what is the problem with when I update the code above instead map method, both give the correct output?
explain to me this behind the scene code sandbox link
Upvotes: 0
Views: 46
Reputation: 10264
When you update your state
you should take care of immutable
.
onUpdateItem = i => {
//this.state.list[i]++;
//this.setState({
// list: this.state.list,
//})
this.setState({
list: this.state.list.map((value,index)=>{
if(i === index) return value+1;
return value;
})
});
}
If you are not maintaining immutable, your app will not work what you expected.
React states are updated follow life-cycle. if without immutability, it means you are breaking the life-cycle.
Upvotes: 1
Reputation: 2343
Here is the reason:
When you mutate an array, say list[i]++
the identity of the array is not changed so listBefore ==== listAfter
, while you map over the array listBefore !== listAfter
, when you invoke setState
, ALL the children component will be invoked again by default even if you put nothing inside setState
. Because react can not tell if the children update is necessary by default and it is a waste of resources actually.
You can prevent this from happening by telling the Children "Do NOT update" by calling shouldComponentUpdate
or simply use PureComponent
.
And the way to tell if updates are necessary is to compare using ===
In addition, Even if you do not care about performance. you should never do this. It will cause some debuggable bugs in some cases mainly because the updates in react is NOT synchronized. I never encounter by the way because I do not even dare to try
Upvotes: 1