tui.calendar
tui.calendar copied to clipboard
When resizing event `beforeUpdateEvent` called multiple times in month view
Version
v.2.1.2
Test Environment
Chrome
Current Behavior
// 'onBeforeUpdateEvent' logged 5 times in console when I resize event
const onBeforeUpdateEvent: ExternalEventTypes['beforeUpdateEvent'] = res=>{
consle.log('onBeforeUpdateEvent');
}
<Calendar onBeforeUpdateEvent={onBeforeUpdateEvent}/>
Expected Behavior
I'm trying to use my own update event function with onBeforeUpdateEvent. Dragging to another day works well... But when resize event,onBeforeUpdateEvent called 5 times so my custom update event happens multiple times too. I'm wondering is there any solution to solve this problem.
@FFloou
I couldn't reproduce the problem you mentioned. Can you provide any example code reproducing the same problem?
FYI it might be related to the equality check between props while re-render.
https://github.com/nhn/tui.calendar/blob/main/apps/react-calendar/docs/en/guide/getting-started.md#%EF%B8%8F-note-for-passing-props
Closing since there's been no feedback and it cannot be reproduced.
Sorry to necro-bump this issue but I'm seeing the same behavior unfortunately. I'm using the react component via a webcomponent wrapper called by an Elm app and the React component is only being rendered once as the calendar instance is in a ref.
But when I drag-n-drop the drag handle of an existing event the onBeforeUpdateEvent
callback is being fired multiple times.
Here's the component
const TuiCalendar = ({
timescale: view,
events, cursor, toElm: toElm_, dialogClosed
}) => {
const tuiRef = useRef(null)
const tui = useCallback(() => tuiRef.current?.getInstance?.(), [])
useEffect(() => tui().setDate(cursor), [tui, cursor])
useEffect(() => {
if (dialogClosed) {
tui().clearGridSelections()
}
}, [tui, dialogClosed])
const toElm = useCallback((type, body) => {
toElm_(`tui_${ type }`, body)
}, [toElm_])
const onClickEvent = useCallback(({ event }) => {
toElm('event_clicked', event)
}, [toElm])
const onSelectDateTime = useCallback((evt) => {
const start = evt.start.getTime()
const end = evt.end.getTime()
toElm('range_selected', { ...evt, start, end })
}, [toElm])
const onBeforeUpdateEvent = useCallback((updates) => {
const { event, changes } = updates
tui().updateEvent(event.id, event.calendarId, changes)
const start = (changes.start ?? event.start)?.getTime()
const end = (changes.end ?? event.end)?.getTime()
toElm('range_updated', { ...event, start, end })
}, [tui, toElm])
return (
<Tui
// Config
ref={ tuiRef }
height="100%"
view={ view }
events={ events }
// Callbacks / Handlers
onSelectDateTime={ onSelectDateTime }
onClickEvent={ onClickEvent }
// Mutations
onBeforeUpdateEvent={ onBeforeUpdateEvent }
/>
)
}
TuiCalendar.propTypes = Tui.propTypes
@erlandsona
I wonder if the TuiCalendar
component's props bypass the wrapper's equality check.
Can you give us any sample sandbox(codesandbox, stackbtliz, etc.) to reproduce this problem?
Same problem
I confirmed that It occurs when you resize any all-day event in the month view.
There might be a problem in this function but I cannot look deeper at this moment.
I'm new to using ToastUI Calendar but I've just come across this same issue.
As discussed it only happens when resizing events and it can be for an all day or timed event.
The problem looks to be that the function ResizingGuideByRow() is called once per row and this calls useDayGridMonthEventResize() which runs the beforeUpdateEvent.
You can see this if you setup the calendar with isAlways6Weeks: false and then on a month that shows 4 or 5 rows the number of calls to beforeUpdateEvent is the same.
I've only looked at the code briefly and I can't see exactly how it's supposed to be working but to me it seems that either:-
- All of the rows should be processed and then the beforeUpdateEvent should be called once.
- The 'shouldUpdate' check that surrounds the beforeUpdateEvent should be changed to take into account the rowIndex so the beforeUpdateEvent is only called when it matches the event being resized.
In useDayGridMonthEventResize() if you change the line
const shouldUpdate = !isDraggingCanceled && (currentGridPos.rowIndex === eventStartDateRowIndex && currentGridPos.columnIndex >= eventStartDateColumnIndex || currentGridPos.rowIndex > eventStartDateRowIndex);
to
const shouldUpdate = !isDraggingCanceled && (rowIndex === eventStartDateRowIndex && (currentGridPos.columnIndex >= eventStartDateColumnIndex || currentGridPos.rowIndex > eventStartDateRowIndex));
then this seems to fix the problem however it seems to me that a rowIndex check should be taking place much earlier.
I found that this issue is still opened... This issue seems a problem of calendar itself and it takes some time to be fixed.
What I wanted was fetching API only once which included in update function, so I ended up wrapping with debounce.
const onBeforeUpdateEvent: ExternalEventTypes['beforeUpdateEvent'] = _.debounce(res=>{
consle.log('onBeforeUpdateEvent');
}, 50)