Skip to content

Commit dbcb92f

Browse files
committed
time table - hoefully fixed that race condition on the necessary row updated and rendering, time table freezes items array
1 parent 107e28b commit dbcb92f

File tree

2 files changed

+99
-80
lines changed

2 files changed

+99
-80
lines changed

library/src/components/timetable/TimeTableRows.tsx

Lines changed: 74 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -214,19 +214,6 @@ export default function TimeTableRows<
214214
// and it should be only set to 0 when the group rows change
215215
//const groupRowsRenderedIdxRef = useRef(groupRowsRenderedIdx)
216216

217-
if (
218-
slotsArrayCurrent.current !== slotsArray ||
219-
viewTypeCurrent.current !== viewType ||
220-
timeFrameDayCurrent.current !== timeFrameDay
221-
) {
222-
// reset the rendered cells
223-
renderedGroups.current.clear()
224-
slotsArrayCurrent.current = slotsArray
225-
viewTypeCurrent.current = viewType
226-
timeFrameDayCurrent.current = timeFrameDay
227-
setGroupRowsRendered([])
228-
}
229-
230217
const rateLimiterIntersection = useIdleRateLimitHelper(renderIdleTimeout)
231218
const rateLimiterRendering = useIdleRateLimitHelper(renderIdleTimeout)
232219
const debounceIntersection = useDebounceHelper(intersectionStackDelay)
@@ -347,76 +334,90 @@ export default function TimeTableRows<
347334
}, [intersectionContainerRef.current, headerRef.current, rowHeight])
348335

349336
const currentGroupRowsRef = useRef(groupRows)
350-
const [currentGroupRows, setCurrentGroupRows] = useState(groupRows)
337+
338+
if (
339+
slotsArrayCurrent.current !== slotsArray ||
340+
viewTypeCurrent.current !== viewType ||
341+
timeFrameDayCurrent.current !== timeFrameDay
342+
) {
343+
// reset the rendered cells
344+
renderedGroups.current.clear()
345+
slotsArrayCurrent.current = slotsArray
346+
viewTypeCurrent.current = viewType
347+
timeFrameDayCurrent.current = timeFrameDay
348+
currentGroupRowsRef.current.clear()
349+
//setCurrentGroupRows(groupRows)
350+
}
351351

352352
//** ------- CHANGE DETECTION ------ */
353353
// handle changes in the group rows
354-
if (groupRows !== currentGroupRows) {
355-
setCurrentGroupRows((currentGroupRows) => {
356-
changedGroupRows.current.clear()
357-
if (!groupRows) {
358-
renderedGroups.current.clear()
359-
refCollection.current = []
360-
setGroupRowsRendered([])
361-
console.log("TimeTable - group rows are null")
362-
return groupRows
363-
}
354+
if (groupRows !== currentGroupRowsRef.current) {
355+
//changedGroupRows.current.clear() -> this misses changes on fast updates where the currentGroupRowsRef is not yet updated
356+
if (!groupRows) {
357+
renderedGroups.current.clear()
358+
refCollection.current = []
359+
setGroupRowsRendered([])
360+
console.log("TimeTable - group rows are null")
361+
return groupRows
362+
}
364363

365-
if (groupRowsRendered.length > groupRows.size) {
366-
// shorten and remove rendered elements array, if too long
367-
console.info(
368-
`Timetable - shorten rendered elements array from ${groupRowsRendered.length} to ${groupRows.size}`,
369-
)
370-
setGroupRowsRendered(groupRowsRendered.slice(0, groupRows.size))
371-
refCollection.current.length = groupRows.size
372-
}
364+
if (groupRowsRendered.length > groupRows.size) {
365+
// shorten and remove rendered elements array, if too long
366+
console.info(
367+
`Timetable - shorten rendered elements array from ${groupRowsRendered.length} to ${groupRows.size}`,
368+
)
369+
setGroupRowsRendered(groupRowsRendered.slice(0, groupRows.size))
370+
refCollection.current.length = groupRows.size
371+
}
373372

374-
// determine when new ones start
375-
let changedFound = -1
376-
const keys = groupRows.keys().toArray()
377-
let updateCounter = 0
378-
for (let i = 0; i < keys.length; i++) {
379-
const group = keys[i]
380-
const rows = groupRows.get(group)
381-
const currentRows = currentGroupRows.get(group)
382-
if (
383-
(rows !== currentRows &&
384-
renderGroupRangeRef.current[0] > -1 &&
385-
i >= renderGroupRangeRef.current[0] &&
386-
i <= renderGroupRangeRef.current[1]) ||
387-
rows?.length !== currentRows?.length
388-
) {
389-
if (changedFound === -1) {
390-
changedFound = i
391-
}
392-
updateCounter++
393-
changedGroupRows.current.add(i)
373+
// determine when new ones start
374+
let changedFound = -1
375+
const keys = groupRows.keys().toArray()
376+
let updateCounter = 0
377+
for (let i = 0; i < keys.length; i++) {
378+
const group = keys[i]
379+
const rows = groupRows.get(group)
380+
const currentRows = currentGroupRowsRef.current.get(group)
381+
if (
382+
(rows !== currentRows &&
383+
renderGroupRangeRef.current[0] > -1 &&
384+
i >= renderGroupRangeRef.current[0] &&
385+
i <= renderGroupRangeRef.current[1]) ||
386+
rows?.length !== currentRows?.length
387+
) {
388+
if (changedFound === -1) {
389+
changedFound = i
394390
}
391+
updateCounter++
392+
changedGroupRows.current.add(i)
395393
}
396-
for (const changedG of changedGroupRows.current) {
397-
if (changedG > keys.length - 1) {
398-
// delete obsolete change
399-
changedGroupRows.current.delete(changedG)
400-
}
394+
}
395+
for (const changedG of changedGroupRows.current) {
396+
if (changedG > keys.length - 1) {
397+
// delete obsolete change
398+
changedGroupRows.current.delete(changedG)
401399
}
402-
for (const renderedG of renderedGroups.current) {
403-
if (renderedG > keys.length - 1) {
404-
// delete obsolete change
405-
renderedGroups.current.delete(renderedG)
406-
}
400+
}
401+
for (const renderedG of renderedGroups.current) {
402+
if (renderedG > keys.length - 1) {
403+
// delete obsolete change
404+
renderedGroups.current.delete(renderedG)
407405
}
406+
}
408407

409-
if (updateCounter) {
410-
console.log(
411-
`TimeTable - group rows require updated rendering ${updateCounter}, with first ${changedFound}`,
412-
renderGroupRangeRef.current,
413-
currentGroupRowsRef.current.size,
414-
groupRows.size,
415-
)
416-
}
417-
currentGroupRowsRef.current = groupRows
418-
return groupRows
419-
})
408+
if (updateCounter) {
409+
console.log(
410+
`TimeTable - group rows require updated rendering ${updateCounter}, with first ${changedFound}`,
411+
renderGroupRangeRef.current,
412+
currentGroupRowsRef.current.size,
413+
groupRows.size,
414+
)
415+
} else {
416+
console.log(
417+
"TimeTable - group rows do not require updated rendering",
418+
)
419+
}
420+
currentGroupRowsRef.current = groupRows
420421
}
421422

422423
//** ------- SCROLL HANDLING ------ */

library/src/components/timetable/useGoupRows.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ export function useGroupRows<
8282
maxRowCountOfSingleGroup.current = 0
8383
itemsOutsideOfDayRange.current = {}
8484
itemsWithSameStartAndEnd.current = {}
85-
console.info("TimeTable - clearing group rows")
85+
console.info(
86+
`TimeTable - clearing group rows in clearGroupRows callback - recalculating ${currentEntries.current?.length || 0} group rows`,
87+
)
8688
groupRowsToCalc.current.clear()
8789
if (currentEntries.current?.length) {
8890
for (let i = 0; i < currentEntries.current.length; i++) {
@@ -95,7 +97,9 @@ export function useGroupRows<
9597
const calculateGroupRows = useCallback(() => {
9698
if (!currentEntries.current) {
9799
if (Object.keys(groupRowsState.current).length) {
98-
console.warn("TimeTable - no entries, clearing group rows")
100+
console.info(
101+
"TimeTable - no entries, clearing group rows in calculateGroupRows",
102+
)
99103
rowCount.current = 0
100104
maxRowCountOfSingleGroup.current = 0
101105
itemsOutsideOfDayRange.current = {}
@@ -128,6 +132,7 @@ export function useGroupRows<
128132
}
129133

130134
for (const i of groupRowsToCalc.current) {
135+
//console.log(`TimeTable - calculating group rows of ${i}. group`)
131136
const entry = currEntries[i]
132137
if (!entry) {
133138
console.error("TimeTable - entry not found", i)
@@ -216,14 +221,15 @@ export function useGroupRows<
216221
currentTimeSlots.current = slotsArray
217222
currentTimeFrameDay.current = timeFrameDay
218223
currentViewType.current = viewType
224+
console.info(
225+
`TimeTable - require new group rows, clearing group rows, new entry count ${entries.length}`,
226+
)
219227
clearGroupRows()
220228
rateLimiterCalc(calculateGroupRows)
221229
}
222230

223231
if (currentEntries.current !== entries) {
224232
// check what needs to be removed, recalculated or added
225-
console.info("TimeTable - entries changed, recalculating group rows")
226-
227233
const updatedGroupRows: Map<G, ItemRowEntry<I>[][] | null> = new Map<
228234
G,
229235
ItemRowEntry<I>[][] | null
@@ -233,10 +239,15 @@ export function useGroupRows<
233239
const updatedItemsOutsideOfDayRange: { [groupId: string]: I[] } = {}
234240
const updatedItemsWithSameStartAndEnd: { [groupId: string]: I[] } = {}
235241
let updateCounter = 0
242+
let stillCalcRequired = 0
236243

237244
for (let i = 0; i < entries.length; i++) {
238245
const entry = entries[i]
239246
const currEntry = currentEntries.current?.[i]
247+
// freeze the items array to get errors when the items array is changed but not the reference, and the changes would not be recognized
248+
if (entry.items) {
249+
Object.freeze(entry.items)
250+
}
240251
if (
241252
currEntry &&
242253
currEntry === entry &&
@@ -261,17 +272,24 @@ export function useGroupRows<
261272
itemsWithSameStartAndEnd.current[entry.group.id]
262273
}
263274
}
264-
updatedGroupRows.set(entry.group, _groupRows)
275+
if (_groupRows) {
276+
updatedGroupRows.set(entry.group, _groupRows)
277+
} else {
278+
// if it is undefined, we need to recalculate the group rows
279+
updatedGroupRows.set(entry.group, null)
280+
++stillCalcRequired
281+
groupRowsToCalc.current.add(i)
282+
}
265283
// do we need to recalculate the group rows?
266284
} else {
267-
updateCounter++
285+
++updateCounter
268286
updatedGroupRows.set(entry.group, null)
269287
groupRowsToCalc.current.add(i)
270288
}
271289
}
272290
currentEntries.current = entries
273291
console.info(
274-
`TimeTable - updating ${updateCounter} group rows`,
292+
`TimeTable - entries changed, updating ${updateCounter} group rows with ${stillCalcRequired} still requiring calculation`,
275293
updatedGroupRows,
276294
)
277295
rowCount.current = updatedRowCount

0 commit comments

Comments
 (0)