Reputation: 91
I am building a calendar React.js app.
When I click on a cell in my calendar, it creates a new event, it is added to an EventList state.
EventList = [{},{},{},{}];
When I create a new event I need to update the width property in all other events in this array to make them visible.
const createEvent = (e) => {
let startTime = e.target.id;
let endTime = day[day.indexOf(e.target.id) + 1];
let newEvent = {
id: uuid(),
startTime,
endTime,
height: columnHeight,
width: 90,
seq: [startTime, endTime],
};
let updEvents = [...events, newEvent];
setevents(updEvents);
console.log(newEvent.seq);
getCollisions()
};
const getCollisions = () => {
let zIndex = 0;
setzIndexState(0);
for (let slot of day) {
let eventsInThisSlot = events.filter((event) => (
event.startTime === slot
));
if (eventsInThisSlot.length > 0) {
console.log('eventsInThisSlot', eventsInThisSlot)
let sorted = sortArrays(eventsInThisSlot);
let width = 100;
let updEvents = [...events];
let index = -1;
for (let event of sorted) {
width = findParentWidth(slot);
index = updEvents.findIndex(obj => obj.id === event.id);
updEvents[index].width = width * (1 - (sorted.indexOf(event) / sorted.length));
updEvents[index].zIndex = zIndex;
console.log('zindex', updEvents[index].zIndex)
zIndex++;
setevents([
...updEvents
]);
};
}
}
setzIndexState(zIndex);
}
My getCollisions function needs to go through the entire list and update the widths after calculating the correct proportions.
The first event gets added ok, however when I try to add a second event, it doesn't get added.
I think the second function has to be run after I've made sure that the element has been added to the state.
I tried tho think of a solution using useEffect but of course this creates an infinite loop.
Upvotes: 0
Views: 40
Reputation: 78
const createEvent = (e) => {
let startTime = e.target.id;
let endTime = day[day.indexOf(e.target.id) + 1];
let newEvent = {
id: uuid(),
startTime,
endTime,
height: columnHeight,
width: 90,
seq: [startTime, endTime],
};
let updEvents = [...events, newEvent];
// setevents(updEvents); // <-- update update your state after getColiisions done
console.log(newEvent.seq);
getCollisions(updEvents); // <-- pass all the new events
};
And then
const getCollisions = (allEvents) => { // <--- get the events
let zIndex = 0;
setzIndexState(0);
let updEvents = [...events]; // <--- create new updEvents
for (let slot of day) {
let eventsInThisSlot = allEvents.filter((event) => ( // <-- use the events arguments.
event.startTime === slot
));
if (eventsInThisSlot.length > 0) {
console.log('eventsInThisSlot', eventsInThisSlot)
let sorted = sortArrays(eventsInThisSlot);
let width = 100;
let index = -1;
for (let event of sorted) {
width = findParentWidth(slot);
index = updEvents.findIndex(obj => obj.id === event.id);
updEvents[index].width = width * (1 - (sorted.indexOf(event) / sorted.length));
updEvents[index].zIndex = zIndex;
console.log('zindex', updEvents[index].zIndex)
zIndex++;
};
}
}
setevents([ // <--- set the event at once
...updEvents
]);
setzIndexState(zIndex);
}
if you need to use useEffect hook, I think better to set the event state as:
const [event, setevent] = useState({
data: [],
version: 0
});
and then set the version increment by 1 in the createEvent method as like this
const createEvent = (e) => {
...
let updEvents = [...events, newEvent];
setevents({
data: updEvents,
version: events.version+1 //<--- increment version just in createEvent method
});
console.log(newEvent.seq);
getCollisions()
};
and then hook the useEffect like this...
useEffect(() => {
...
}, [events.version]);
Upvotes: 1