Reputation: 57
am I missing something? I'm using es6 style to add to an empty array in this.state, but nothing is getting pushed to state.
I should be getting two inside of the array, but after console.logging nothing is showing. and my screen is not rerendering, since coponentDidUpdate is not running.
class HomeModal extends Component {
constructor(props) {
super(props);
this.state = {
specificList: []
};
this.updateState = this.updateState.bind(this);
}
componentWillMount() {
this.updateState();
}
componentDidUpdate() {
console.log("after update: ", this.state.specificList);
}
updateState = () => {
this.props.completeList.forEach(index => {
index.list.forEach(innerArr => {
if (innerArr.muscleGroup === this.props.selectedBodyPart) {
console.log("test: ", innerArr);
this.setState({
specificList: [...this.state.specificList, innerArr.title]
});
}
});
console.log("after each loop: ", this.state.specificList);
});
};
// console.log results
06:22:48: test: Object {
06:22:48: "muscleGroup": "Chest",
06:22:48: "title": "Barbell Bench Press",
06:22:48: }
06:22:48: after each loop: Array []
06:22:48: test: Object {
06:22:48: "muscleGroup": "Chest",
06:22:48: "title": "Barbell Bench Press",
06:22:48: }
06:22:48: after each loop: Array []
06:22:48: after each loop: Array []
6:08:04: Object { // what innerArr the object looks like
06:08:04: "muscleGroup": "Chest",
06:08:04: "title": "Barbell Bench Press",
06:08:04: }
Upvotes: 0
Views: 97
Reputation: 339
It would be best to call setState once you have looped through both of you loops. For eg. you can do something like this:
updateState = () => {
let temp = this.state.specificList;
this.props.completeList.forEach(index => {
index.list.forEach(innerArr => {
if (innerArr.muscleGroup === this.props.selectedBodyPart) {
console.log("test: ", innerArr);
temp.push(innerArr.title);
}
});
console.log("after each loop: ", temp)
});
this.setState({ specificList: temp });
}
Upvotes: 0
Reputation: 101662
setState
is asynchronous. That means that the value of the state values don't update immediately.
What you are doing is looping through a series of values and setting the state of specificList
to the concatenation of the current value of specificList
plus a single item from the array.
So if specificList
were ['a', 'b', 'c']
and the array you're looping over were [1, 2, 3]
, then you would essentially be calling:
setState({ specificList: ['a', 'b', 'c', 1] })
setState({ specificList: ['a', 'b', 'c', 2] })
setState({ specificList: ['a', 'b', 'c', 3] })
You can see how all of the values of the array except for the last one get left out.
One way to fix this is to pass a function to setState
instead of a value. This will allow you to work with setState
's asynchronous behavior:
updateState = () => {
this.props.completeList.forEach(index => {
index.list.forEach(innerArr => {
if (innerArr.muscleGroup === this.props.selectedBodyPart) {
console.log("test: ", innerArr);
this.setState(({ specificList } => ({
specificList: [...specificList, innerArr.title]
}));
}
});
});
};
Upvotes: 0
Reputation: 22911
Some small notes on .setState()
from the docs:
React may batch multiple
setState()
calls into a single update for performance.Because
this.props
andthis.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
I would simply use another object at the start of the loop (Copying from the current state), modify that variable in the loop, and then do one .setState()
at the very end, after all your loops are done.
Upvotes: 2
Reputation: 2573
Try to log the output with setState callback, like this:
this.setState({
specificList: [...this.state.specificList, innerArr.title]
}, () => {
console.log("after each loop: ", this.state.specificList);
});
Upvotes: 1