I've been working with new lifecycles of React v16. It works great when we pare only a single key. But when it es to pare a large data structures like an Arrays of objects, the deep parison will bee very costly.
I have use case like this in which I have an array ob objects stored in redux,
const readings =[
{
id: ...,
name: ...',
unit:...,
value: ...,
timestamp: ...,
active: true,
},
...
]
Whenever active state of any objects get changed I dispatch an action to update redux state to be same for all connected ponents with that reducer.
class Readings extends Component {
state = {
readings:[],
};
static getDerivedStateFromProps(nextProps, prevState) {
if ( // parsion of readings array with prevState) {
return {
readings: nextProps.readings,
};
}
return null;
}
ponentDidUpdate(prevProps) {
if ( // parsion of readings array with prevState) {
// perform an operation here to manipulate new props and setState to re render the p
// this causes infinite loop
}
}
render() {
...
}
}
const mapStateToProps = state => ({
readings: state.readings.readings,
});
export default connect(
mapStateToProps,
)(Readings));
How can I avoid infinite loop on setState in ponentDidUpdate, I don't want to do deep parison of readings array. Is there a better solution to handle this case?
Your suggestions will be highly appreciated.
I've been working with new lifecycles of React v16. It works great when we pare only a single key. But when it es to pare a large data structures like an Arrays of objects, the deep parison will bee very costly.
I have use case like this in which I have an array ob objects stored in redux,
const readings =[
{
id: ...,
name: ...',
unit:...,
value: ...,
timestamp: ...,
active: true,
},
...
]
Whenever active state of any objects get changed I dispatch an action to update redux state to be same for all connected ponents with that reducer.
class Readings extends Component {
state = {
readings:[],
};
static getDerivedStateFromProps(nextProps, prevState) {
if ( // parsion of readings array with prevState) {
return {
readings: nextProps.readings,
};
}
return null;
}
ponentDidUpdate(prevProps) {
if ( // parsion of readings array with prevState) {
// perform an operation here to manipulate new props and setState to re render the p
// this causes infinite loop
}
}
render() {
...
}
}
const mapStateToProps = state => ({
readings: state.readings.readings,
});
export default connect(
mapStateToProps,
)(Readings));
How can I avoid infinite loop on setState in ponentDidUpdate, I don't want to do deep parison of readings array. Is there a better solution to handle this case?
Your suggestions will be highly appreciated.
Share Improve this question asked Oct 29, 2018 at 10:33 Sakhi MansoorSakhi Mansoor 8,1225 gold badges23 silver badges38 bronze badges 2-
1
Just a thought - do you need to derive state here, why not just keep it in props? Also, what do you do with the readings? Perhaps you could restructure to remove the need for a deep parison. If you display something for each reading, why not have a
<Reading />
ponent for each of them. This could be aPureComponent
and each<Reading />
can shallow pare the object reference, with no need for a deep parison in the parent. – user195257 Commented Oct 29, 2018 at 11:50 - yes you're right. Keeping only props solved the problem. Thank you – Sakhi Mansoor Commented Oct 29, 2018 at 12:13
2 Answers
Reset to default 6Ideally, you make immutable changes to your reducer and keep the reducer state level low.
So if your array consists of many objects and you need to dispatch based on some attribute change, you should replace the whole readings array using spread operator or using some immutable library e.g immutablejs. Then in your ponentDidupdate you can have something like :
ponentDidUpdate(prevProps) {
const {
readings,
} = this.props
const {
readings: prevReadings,
} = prevProps
if (readings !== prevReadings) {
//dispatch something
}
}
Thanks feedbacks are wele.
First read another answer, If that didn't work for you, then:
- Make sure you're paring two arrays with :
ponentDidUpdate(prevProps){
if(JSON.stringify(prevProps.todos) !== JSON.stringify(this.props.todos){...}
}
- Make sure you are changing the passed prop (state in parent) after deep cloning it:
let newtodos = JSON.parse(JSON.stringify(this.state.todos));
newtodos[0].text = 'changed text';
this.setState({ todos : newtodos });
(Note that Shallow clone doesn't work, since that way you change the objects directly)