virtual-scroller 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +13 -11
  3. package/bundle/virtual-scroller-dom.js +1 -1
  4. package/bundle/virtual-scroller-dom.js.map +1 -1
  5. package/bundle/virtual-scroller-react.js +1 -1
  6. package/bundle/virtual-scroller-react.js.map +1 -1
  7. package/bundle/virtual-scroller.js +1 -1
  8. package/bundle/virtual-scroller.js.map +1 -1
  9. package/commonjs/DOM/ItemsContainer.js +10 -3
  10. package/commonjs/DOM/ItemsContainer.js.map +1 -1
  11. package/commonjs/DOM/VirtualScroller.js +13 -1
  12. package/commonjs/DOM/VirtualScroller.js.map +1 -1
  13. package/commonjs/ItemHeights.js +5 -5
  14. package/commonjs/ItemHeights.js.map +1 -1
  15. package/commonjs/ItemNotRenderedError.js +64 -0
  16. package/commonjs/ItemNotRenderedError.js.map +1 -0
  17. package/commonjs/Layout.test.js +10 -0
  18. package/commonjs/Layout.test.js.map +1 -1
  19. package/commonjs/VirtualScroller.js +23 -5
  20. package/commonjs/VirtualScroller.js.map +1 -1
  21. package/commonjs/VirtualScroller.layout.js +81 -39
  22. package/commonjs/VirtualScroller.layout.js.map +1 -1
  23. package/commonjs/VirtualScroller.onRender.js +97 -45
  24. package/commonjs/VirtualScroller.onRender.js.map +1 -1
  25. package/commonjs/VirtualScroller.state.js +50 -18
  26. package/commonjs/VirtualScroller.state.js.map +1 -1
  27. package/commonjs/react/VirtualScroller.js +31 -46
  28. package/commonjs/react/VirtualScroller.js.map +1 -1
  29. package/commonjs/react/useItemKeys.js +11 -3
  30. package/commonjs/react/useItemKeys.js.map +1 -1
  31. package/commonjs/react/useOnChange.js +19 -0
  32. package/commonjs/react/useOnChange.js.map +1 -0
  33. package/commonjs/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +7 -7
  34. package/commonjs/react/useOnItemHeightDidChange.js.map +1 -0
  35. package/commonjs/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +15 -14
  36. package/commonjs/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  37. package/commonjs/react/useState.js +162 -69
  38. package/commonjs/react/useState.js.map +1 -1
  39. package/commonjs/react/useStyle.js +3 -5
  40. package/commonjs/react/useStyle.js.map +1 -1
  41. package/commonjs/react/useUpdateItemKeysOnItemsChange.js +61 -0
  42. package/commonjs/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  43. package/commonjs/test/ItemsContainer.js +22 -1
  44. package/commonjs/test/ItemsContainer.js.map +1 -1
  45. package/commonjs/utility/debug.js +30 -6
  46. package/commonjs/utility/debug.js.map +1 -1
  47. package/dom/index.d.ts +1 -1
  48. package/index.cjs +2 -0
  49. package/index.d.ts +7 -1
  50. package/index.js +1 -0
  51. package/modules/DOM/ItemsContainer.js +8 -3
  52. package/modules/DOM/ItemsContainer.js.map +1 -1
  53. package/modules/DOM/VirtualScroller.js +13 -1
  54. package/modules/DOM/VirtualScroller.js.map +1 -1
  55. package/modules/ItemHeights.js +5 -5
  56. package/modules/ItemHeights.js.map +1 -1
  57. package/modules/ItemNotRenderedError.js +57 -0
  58. package/modules/ItemNotRenderedError.js.map +1 -0
  59. package/modules/Layout.test.js +10 -0
  60. package/modules/Layout.test.js.map +1 -1
  61. package/modules/VirtualScroller.js +17 -5
  62. package/modules/VirtualScroller.js.map +1 -1
  63. package/modules/VirtualScroller.layout.js +78 -39
  64. package/modules/VirtualScroller.layout.js.map +1 -1
  65. package/modules/VirtualScroller.onRender.js +98 -46
  66. package/modules/VirtualScroller.onRender.js.map +1 -1
  67. package/modules/VirtualScroller.state.js +50 -18
  68. package/modules/VirtualScroller.state.js.map +1 -1
  69. package/modules/react/VirtualScroller.js +31 -46
  70. package/modules/react/VirtualScroller.js.map +1 -1
  71. package/modules/react/useItemKeys.js +8 -3
  72. package/modules/react/useItemKeys.js.map +1 -1
  73. package/modules/react/useOnChange.js +11 -0
  74. package/modules/react/useOnChange.js.map +1 -0
  75. package/modules/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +6 -6
  76. package/modules/react/useOnItemHeightDidChange.js.map +1 -0
  77. package/modules/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -13
  78. package/modules/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  79. package/modules/react/useState.js +156 -73
  80. package/modules/react/useState.js.map +1 -1
  81. package/modules/react/useStyle.js +3 -5
  82. package/modules/react/useStyle.js.map +1 -1
  83. package/{commonjs/react/useHandleItemIndexesChange.js → modules/react/useUpdateItemKeysOnItemsChange.js} +18 -21
  84. package/modules/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  85. package/modules/test/ItemsContainer.js +20 -1
  86. package/modules/test/ItemsContainer.js.map +1 -1
  87. package/modules/utility/debug.js +31 -6
  88. package/modules/utility/debug.js.map +1 -1
  89. package/package.json +1 -1
  90. package/source/DOM/ItemsContainer.js +8 -3
  91. package/source/DOM/VirtualScroller.js +11 -1
  92. package/source/ItemHeights.js +5 -5
  93. package/source/ItemNotRenderedError.js +16 -0
  94. package/source/Layout.test.js +9 -0
  95. package/source/VirtualScroller.js +14 -3
  96. package/source/VirtualScroller.layout.js +77 -38
  97. package/source/VirtualScroller.onRender.js +95 -42
  98. package/source/VirtualScroller.state.js +57 -20
  99. package/source/react/VirtualScroller.js +28 -39
  100. package/source/react/useItemKeys.js +9 -2
  101. package/source/react/useOnChange.js +11 -0
  102. package/source/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +5 -5
  103. package/source/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -11
  104. package/source/react/useState.js +159 -71
  105. package/source/react/useStyle.js +2 -2
  106. package/source/react/{useHandleItemIndexesChange.js → useUpdateItemKeysOnItemsChange.js} +17 -9
  107. package/source/test/ItemsContainer.js +22 -1
  108. package/source/utility/debug.js +18 -4
  109. package/commonjs/react/useHandleItemIndexesChange.js.map +0 -1
  110. package/commonjs/react/useHandleItemsPropertyChange.js.map +0 -1
  111. package/commonjs/react/useOnItemHeightChange.js.map +0 -1
  112. package/modules/react/useHandleItemIndexesChange.js +0 -45
  113. package/modules/react/useHandleItemIndexesChange.js.map +0 -1
  114. package/modules/react/useHandleItemsPropertyChange.js.map +0 -1
  115. package/modules/react/useOnItemHeightChange.js.map +0 -1
@@ -52,7 +52,13 @@ export default function createStateHelpers({
52
52
 
53
53
  this.getState().itemStates[i] = newItemState
54
54
 
55
- // Schedule the item state update for after the new items have been rendered.
55
+ // If there was a request for `setState()` with new `items`, then the changes
56
+ // to `currentState.itemStates[]` made above would be overwritten when that
57
+ // pending `setState()` call gets applied.
58
+ // To fix that, the updates to current `itemStates[]` are noted in
59
+ // `this.itemStatesThatChangedWhileNewItemsWereBeingRendered` variable.
60
+ // That variable is then checked when the `setState()` call with the new `items`
61
+ // has been updated.
56
62
  if (this.newItemsWillBeRendered) {
57
63
  if (!this.itemStatesThatChangedWhileNewItemsWereBeingRendered) {
58
64
  this.itemStatesThatChangedWhileNewItemsWereBeingRendered = {}
@@ -78,9 +84,25 @@ export default function createStateHelpers({
78
84
  }
79
85
  this._isSettingNewItems = undefined
80
86
 
81
- // Update `state`.
87
+ this.waitingForRender = true
88
+
89
+ // Store previous `state`.
82
90
  this.previousState = this.getState()
83
- this._updateState(stateUpdate)
91
+
92
+ // If it's the first call to `this.updateState()` then initialize
93
+ // the most recent `setState()` value to be the current state.
94
+ if (!this.mostRecentSetStateValue) {
95
+ this.mostRecentSetStateValue = this.getState()
96
+ }
97
+
98
+ // Accumulates all "pending" state updates until they have been applied.
99
+ this.mostRecentSetStateValue = {
100
+ ...this.mostRecentSetStateValue,
101
+ ...stateUpdate
102
+ }
103
+
104
+ // Update `state`.
105
+ this._setState(this.mostRecentSetStateValue, stateUpdate)
84
106
  }
85
107
 
86
108
  this.getInitialState = () => {
@@ -92,6 +114,7 @@ export default function createStateHelpers({
92
114
 
93
115
  this.useState = ({
94
116
  getState,
117
+ setState,
95
118
  updateState
96
119
  }) => {
97
120
  if (this._isActive) {
@@ -103,17 +126,28 @@ export default function createStateHelpers({
103
126
  }
104
127
 
105
128
  if (render) {
106
- throw new Error('[virtual-scroller] Creating a `VirtualScroller` class instance with a `render()` parameter means using the default (internal) state storage')
129
+ throw new Error('[virtual-scroller] Creating a `VirtualScroller` class instance with a `render()` parameter implies using the default (internal) state storage')
107
130
  }
108
131
 
109
- if (!getState || !updateState) {
110
- throw new Error('[virtual-scroller] When using a custom state storage, one must supply both `getState()` and `updateState()` functions')
132
+ if (setState && updateState) {
133
+ throw new Error('[virtual-scroller] When using a custom state storage, one must supply either `setState()` or `updateState()` function but not both')
134
+ }
135
+
136
+ if (!getState || !(setState || updateState)) {
137
+ throw new Error('[virtual-scroller] When using a custom state storage, one must supply both `getState()` and `setState()`/`updateState()` functions')
111
138
  }
112
139
 
113
140
  this._usesCustomStateStorage = true
114
141
 
115
142
  this._getState = getState
116
- this._updateState = updateState
143
+
144
+ this._setState = (newState, stateUpdate) => {
145
+ if (setState) {
146
+ setState(newState)
147
+ } else {
148
+ updateState(stateUpdate)
149
+ }
150
+ }
117
151
  }
118
152
 
119
153
  this.useDefaultStateStorage = () => {
@@ -121,9 +155,9 @@ export default function createStateHelpers({
121
155
  throw new Error('[virtual-scroller] When using the default (internal) state management, one must supply a `render(state, prevState)` function parameter')
122
156
  }
123
157
 
124
- // Create default `getState()`/`updateState()` functions.
158
+ // Create default `getState()`/`setState()` functions.
125
159
  this._getState = defaultGetState.bind(this)
126
- this._updateState = defaultUpdateState.bind(this)
160
+ this._setState = defaultSetState.bind(this)
127
161
 
128
162
  // When `state` is stored externally, a developer is responsible for
129
163
  // initializing it with the initial value.
@@ -140,17 +174,20 @@ export default function createStateHelpers({
140
174
  this.state = newState
141
175
  }
142
176
 
143
- function defaultUpdateState(stateUpdate) {
144
- // Because this variant of `.updateState()` is "synchronous" (immediate),
145
- // it can be written like `...prevState`, and no state updates would be lost.
146
- // But if it was "asynchronous" (not immediate), then `...prevState`
147
- // wouldn't work in all cases, because it could be stale in cases
148
- // when more than a single `updateState()` call is made before
149
- // the state actually updates, making `prevState` stale.
150
- this.state = {
151
- ...this.state,
152
- ...stateUpdate
153
- }
177
+ function defaultSetState(newState, stateUpdate) {
178
+ // // Because the default state updates are "synchronous" (immediate),
179
+ // // the `...stateUpdate` could be applied over `...this.state`,
180
+ // // and no state updates would be lost.
181
+ // // But if it was "asynchronous" (not immediate), then `...this.state`
182
+ // // wouldn't work in all cases, because it could be stale in cases
183
+ // // when more than a single `setState()` call is made before
184
+ // // the state actually updates, making some properties of `this.state` stale.
185
+ // this.state = {
186
+ // ...this.state,
187
+ // ...stateUpdate
188
+ // }
189
+
190
+ this.state = newState
154
191
 
155
192
  render(this.state, this.previousState)
156
193
 
@@ -7,33 +7,22 @@ import useVirtualScrollerStartStop from './useVirtualScrollerStartStop.js'
7
7
  import useInstanceMethods from './useInstanceMethods.js'
8
8
  import useItemKeys from './useItemKeys.js'
9
9
  import useSetItemState from './useSetItemState.js'
10
- import useOnItemHeightChange from './useOnItemHeightChange.js'
11
- import useHandleItemsPropertyChange from './useHandleItemsPropertyChange.js'
12
- import useHandleItemIndexesChange from './useHandleItemIndexesChange.js'
10
+ import useOnItemHeightDidChange from './useOnItemHeightDidChange.js'
11
+ import useSetNewItemsOnItemsPropertyChange from './useSetNewItemsOnItemsPropertyChange.js'
12
+ import useUpdateItemKeysOnItemsChange from './useUpdateItemKeysOnItemsChange.js'
13
13
  import useClassName from './useClassName.js'
14
14
  import useStyle from './useStyle.js'
15
15
 
16
- // When `items` property changes, `useHandleItemsPropertyChange()` hook detects that
17
- // and calls `VirtualScroller.setItems()` which in turn calls the `updateState()` function.
18
- // At this point, an insignificant optimization could be applied:
19
- // the component could avoid re-rendering the second time.
20
- // Instead, the state update could be applied "immediately" if it originated
21
- // from `.setItems()` function call, eliminating the unneeded second re-render.
22
- //
23
- // I could see how this minor optimization could get brittle when modifiying the code,
24
- // so I put it under a feature flag so that it could potentially be turned off
25
- // in case of any potential weird issues in some future.
26
- //
27
- // Another reason for using this feature is:
28
- //
29
- // Since `useHandleItemsPropertyChange()` runs at render time
30
- // and not after the render has finished (not in an "effect"),
31
- // if the state update was done "conventionally" (by calling `_setNewState()`),
32
- // React would throw an error about updating state during render.
33
- // No one knows what the original error message was.
34
- // Perhaps it's no longer relevant in newer versions of React.
35
- //
36
- const USE_ITEMS_UPDATE_NO_SECOND_RENDER_OPTIMIZATION = true
16
+ // When `items` property changes:
17
+ // * A new `items` property is supplied to the React component.
18
+ // * The React component re-renders itself.
19
+ // * `useSetNewItemsOnItemsPropertyChange()` hook is run.
20
+ // * `useSetNewItemsOnItemsPropertyChange()` hook detects that the `items` property
21
+ // has changed and calls `VirtualScroller.setItems(items)`.
22
+ // * `VirtualScroller.setItems(items)` calls `VirtualScroller.setState()`.
23
+ // * `VirtualScroller.setState()` calls the `setState()` function.
24
+ // * The `setState()` function calls a setter from a `useState()` hook.
25
+ // * The React component re-renders itself the second time.
37
26
 
38
27
  function VirtualScroller({
39
28
  as: AsComponent,
@@ -113,20 +102,19 @@ function VirtualScroller({
113
102
  // This way, React will re-render the component on every state update.
114
103
  const {
115
104
  getState,
116
- updateState,
117
- getNextState
105
+ setState,
106
+ stateToRender
118
107
  } = useState({
119
108
  initialState: _initialState,
120
109
  onRender: virtualScroller.onRender,
121
- itemsProperty,
122
- USE_ITEMS_UPDATE_NO_SECOND_RENDER_OPTIMIZATION
110
+ itemsProperty
123
111
  })
124
112
 
125
113
  // Use custom (external) state storage in the `VirtualScroller`.
126
114
  useMemo(() => {
127
115
  virtualScroller.useState({
128
116
  getState,
129
- updateState
117
+ setState
130
118
  })
131
119
  }, [])
132
120
 
@@ -138,6 +126,7 @@ function VirtualScroller({
138
126
  // "reuse" `itemComponent`s in cases when `items` are changed.
139
127
  const {
140
128
  getItemKey,
129
+ usesAutogeneratedItemKeys,
141
130
  updateItemKeysForNewItems
142
131
  } = useItemKeys({
143
132
  getItemId
@@ -150,27 +139,26 @@ function VirtualScroller({
150
139
  virtualScroller
151
140
  })
152
141
 
153
- // Cache per-item `onItemHeightChange` functions' "references"
142
+ // Cache per-item `onItemHeightDidChange` functions' "references"
154
143
  // so that item components don't get re-rendered needlessly.
155
- const getOnItemHeightChange = useOnItemHeightChange({
144
+ const getOnItemHeightDidChange = useOnItemHeightDidChange({
156
145
  initialItemsCount: itemsProperty.length,
157
146
  virtualScroller
158
147
  })
159
148
 
160
149
  // Calls `.setItems()` if `items` property has changed.
161
- useHandleItemsPropertyChange(itemsProperty, {
150
+ useSetNewItemsOnItemsPropertyChange(itemsProperty, {
162
151
  virtualScroller,
163
152
  // `preserveScrollPosition` property name is deprecated,
164
153
  // use `preserveScrollPositionOnPrependItems` property instead.
165
154
  preserveScrollPosition,
166
- preserveScrollPositionOnPrependItems,
167
- nextItems: getNextState().items
155
+ preserveScrollPositionOnPrependItems
168
156
  })
169
157
 
170
158
  // Updates `key`s if item indexes have changed.
171
- useHandleItemIndexesChange({
159
+ useUpdateItemKeysOnItemsChange(stateToRender.items, {
172
160
  virtualScroller,
173
- itemsBeingRendered: getNextState().items,
161
+ usesAutogeneratedItemKeys,
174
162
  updateItemKeysForNewItems
175
163
  })
176
164
 
@@ -209,7 +197,7 @@ function VirtualScroller({
209
197
 
210
198
  const style = useStyle({
211
199
  tbody,
212
- getNextState
200
+ state: stateToRender
213
201
  })
214
202
 
215
203
  const {
@@ -217,7 +205,7 @@ function VirtualScroller({
217
205
  itemStates,
218
206
  firstShownItemIndex,
219
207
  lastShownItemIndex
220
- } = getNextState()
208
+ } = stateToRender
221
209
 
222
210
  return (
223
211
  <AsComponent
@@ -251,7 +239,8 @@ function VirtualScroller({
251
239
  state={itemStates && itemStates[i]}
252
240
  setState={getSetItemState(i)}
253
241
  onStateChange={getSetItemState(i)}
254
- onHeightChange={getOnItemHeightChange(i)}>
242
+ onHeightChange={getOnItemHeightDidChange(i)}
243
+ onHeightDidChange={getOnItemHeightDidChange(i)}>
255
244
  {item}
256
245
  </Component>
257
246
  )
@@ -1,3 +1,5 @@
1
+ import log from '../utility/debug.js'
2
+
1
3
  import { useRef, useMemo, useCallback } from 'react'
2
4
 
3
5
  export default function useItemKeys({ getItemId }) {
@@ -27,12 +29,16 @@ export default function useItemKeys({ getItemId }) {
27
29
  generateItemKeyPrefix()
28
30
  }, [])
29
31
 
32
+ // If `getItemId()` function is defined, then item `id`s are gonna be the item element `key`s.
33
+ const usesAutogeneratedItemKeys = !getItemId
34
+
30
35
  const generateItemKeyPrefixIfNotUsingItemIds = useCallback(() => {
31
- if (!getItemId) {
36
+ if (usesAutogeneratedItemKeys) {
32
37
  generateItemKeyPrefix()
38
+ log('React: ~ Item key prefix:', itemKeyPrefix.current)
33
39
  }
34
40
  }, [
35
- getItemId,
41
+ usesAutogeneratedItemKeys,
36
42
  generateItemKeyPrefix
37
43
  ])
38
44
 
@@ -54,6 +60,7 @@ export default function useItemKeys({ getItemId }) {
54
60
 
55
61
  return {
56
62
  getItemKey,
63
+ usesAutogeneratedItemKeys,
57
64
  updateItemKeysForNewItems: generateItemKeyPrefixIfNotUsingItemIds
58
65
  }
59
66
  }
@@ -0,0 +1,11 @@
1
+ import { useRef } from 'react'
2
+
3
+ export default function useOnChange(value, onChange) {
4
+ const previousValueRef = useRef(value)
5
+ const previousValue = previousValueRef.current
6
+ previousValueRef.current = value
7
+
8
+ if (value !== previousValue) {
9
+ onChange(value, previousValue)
10
+ }
11
+ }
@@ -1,6 +1,6 @@
1
1
  import { useMemo, useRef, useCallback } from 'react'
2
2
 
3
- export default function useOnItemHeightChange({
3
+ export default function useOnItemHeightDidChange({
4
4
  initialItemsCount,
5
5
  virtualScroller
6
6
  }) {
@@ -12,11 +12,11 @@ export default function useOnItemHeightChange({
12
12
  // Handler functions cache.
13
13
  const cache = useRef(initialCacheValue)
14
14
 
15
- // Caches per-item `onItemHeightChange` functions' "references"
15
+ // Caches per-item `onItemHeightDidChange` functions' "references"
16
16
  // so that item components don't get re-rendered needlessly.
17
- const getOnItemHeightChange = useCallback((i) => {
17
+ const getOnItemHeightDidChange = useCallback((i) => {
18
18
  if (!cache.current[i]) {
19
- cache.current[i] = () => virtualScroller.onItemHeightChange(i)
19
+ cache.current[i] = () => virtualScroller.onItemHeightDidChange(i)
20
20
  }
21
21
  return cache.current[i]
22
22
  }, [
@@ -24,5 +24,5 @@ export default function useOnItemHeightChange({
24
24
  cache
25
25
  ])
26
26
 
27
- return getOnItemHeightChange
27
+ return getOnItemHeightDidChange
28
28
  }
@@ -1,4 +1,6 @@
1
- import { useRef } from 'react'
1
+ import log from '../utility/debug.js'
2
+
3
+ import useOnChange from './useOnChange.js'
2
4
 
3
5
  // If new `items` property is passed:
4
6
  //
@@ -8,13 +10,12 @@ import { useRef } from 'react'
8
10
  //
9
11
  // * Call `VirtualScroller.setItems()` function.
10
12
  //
11
- export default function useHandleItemsPropertyChange(itemsProperty, {
13
+ export default function useSetNewItemsOnItemsPropertyChange(itemsProperty, {
12
14
  virtualScroller,
13
15
  // `preserveScrollPosition` property name is deprecated,
14
16
  // use `preserveScrollPositionOnPrependItems` property instead.
15
17
  preserveScrollPosition,
16
- preserveScrollPositionOnPrependItems,
17
- nextItems
18
+ preserveScrollPositionOnPrependItems
18
19
  }) {
19
20
  // During render, check if the `items` list has changed.
20
21
  // If it has, capture the Y scroll position and updated item element `key`s.
@@ -60,15 +61,13 @@ export default function useHandleItemsPropertyChange(itemsProperty, {
60
61
  // scroll Y position is captured while the "Show previous" button
61
62
  // is still being shown.
62
63
 
63
- const previousItemsProperty = useRef(itemsProperty)
64
- const hasItemsPropertyChanged = itemsProperty !== previousItemsProperty.current
65
- previousItemsProperty.current = itemsProperty
64
+ useOnChange(itemsProperty, (itemsProperty, prevItemsProperty) => {
65
+ log('React: ~ Different `items` property has been passed', itemsProperty)
66
66
 
67
- if (hasItemsPropertyChanged) {
68
67
  let shouldUpdateItems = true
69
68
 
70
69
  // Analyze the upcoming `items` change.
71
- const itemsDiff = virtualScroller.getItemsDiff(nextItems, itemsProperty)
70
+ const itemsDiff = virtualScroller.getItemsDiff(prevItemsProperty, itemsProperty)
72
71
 
73
72
  // `itemsDiff` will be `undefined` in case of a non-incremental items list change.
74
73
  if (itemsDiff) {
@@ -79,12 +78,13 @@ export default function useHandleItemsPropertyChange(itemsProperty, {
79
78
  if (prependedItemsCount === 0 && appendedItemsCount === 0) {
80
79
  // The items order hasn't changed.
81
80
  // No need to update them in `VirtualScroller` or to snapshot the Y scroll position.
81
+ log('React: ~ The `items` elements are identical to the previous ones')
82
82
  shouldUpdateItems = false
83
83
  }
84
84
  }
85
85
 
86
86
  if (shouldUpdateItems) {
87
- // Request to update the `items` in `VirtualScroller`.
87
+ // Make a request to update the `items` in `VirtualScroller`.
88
88
  // This will result in a `setState()` call.
89
89
  // The new items won't be rendered until that state update is applied.
90
90
  virtualScroller.setItems(itemsProperty, {
@@ -93,5 +93,5 @@ export default function useHandleItemsPropertyChange(itemsProperty, {
93
93
  preserveScrollPositionOnPrependItems: preserveScrollPositionOnPrependItems || preserveScrollPosition
94
94
  })
95
95
  }
96
- }
96
+ })
97
97
  }