I am having an issue where I am setting state with a spread operator but the function call in useEffect only ever sets the last value pulled from the API into state.
// get all events to display on load
const getEvents = () => {
console.log(props.id);
axios.get(API.EVENTS.ROOT + props.id).then(
res => {
const data = res.data;
setEvent(data);
console.log(data);
// event start and end dates
setStart(new Date(data.start));
setEnd(new Date(data.finish));
// breakout dates
for (let i = 0; i < data.breakouts.length; i++) {
console.log(data.breakouts[i].start);
data.breakouts[i].start = new Date(data.breakouts[i].start);
data.breakouts[i].end = new Date(data.breakouts[i].end);
console.log(data.breakouts[i].name, "test" + data.breakouts[i].start);
// set date picker initial value
setFields({
...fields,
[data.breakouts[i].name]: data.breakouts[i].start
})
console.log(fields);
}
setBreakoutRow(data.breakouts);
console.log(breakoutRow);
}
).catch(err => {
console.log(err);
})
}
// get events on load
useEffect(() => {
console.log(props);
getEvents();
}, []);
I add the fields state variable or the getEvents function as a dependency it does update the state of fields for all values but it results in an infinite loop of death. This is giving me blank dates in mapped rows for all but the last.
Another item of note is that after the page loads the fields object can be updated no problem through a function call, as so:
const handleDateChange = (dateName, dateValue) => {
console.log(dateName, dateValue);
setFields({
...fields,
[dateName]: dateValue
})
console.log(fields);
}
This leads me to believe there is something wrong with my useEffect hook but I am not sure where it's going wrong.
Reason is how you're accessing previous value to add new element:
for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
setFields({
...fields,
[data.breakouts[i].name]: data.breakouts[i].start
})
}
since fields will be updated only on next render, you are adding single element(but each loop it's different element) to the array.
The same would be without hooks/react:
const start = [];
for(let i = 0; i< 5; i++) console.log([...start, i]);
This will never output [0,1,2,3,4].
What can you do.
const temp = {};
for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
data.breakouts[i].end = new Date(data.breakouts[i].end);
temp[data.breakouts[i].name] = data.breakouts[i].start
}
setFields({
...fields,
...temp
});
for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
setFields(({fields: prevFields}) => ({
...prevFields,
[data.breakouts[i].name]: data.breakouts[i].start
}))
}
I'd prefer first option for 2 reasons:
axios.get there would be some API.getMeaningfullThings returning structure you need; so it's easier to refactorIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With