Skip to content

Commit

Permalink
fix: avoid restoreStateFrom overwriting data when props change
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Apr 29, 2023
1 parent 2e73470 commit 315be28
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
18 changes: 17 additions & 1 deletion examples/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ function generateMessages(length: number): Message[] {
const initialChannelData = Array.from({ length: 3 }, (_, index) => {
return {
id: index,
firstItemIndex: 200000,
name: `Channel ${index}`,
messages: generateMessages(130),
messages: generateMessages(20),
}
})

initialChannelData.push({
id: 3,
firstItemIndex: 200000,
name: 'Channel 3',
messages: generateMessages(1),
})
Expand All @@ -52,6 +54,18 @@ export function Example() {
[currentChannelId, channels]
)

const loadOlderMessages = React.useCallback(() => {
setTimeout(() => {
setChannels((channels) => {
return produce(channels, (draft) => {
const channel = draft.find((x) => x.id === currentChannelId)!
channel.messages.unshift(...generateMessages(20))
channel.firstItemIndex -= 20
})
})
}, 1000)
}, [currentChannelId, channels])

const selectChannel = React.useCallback(
(id: number) => {
if (currentChannelId !== null) {
Expand Down Expand Up @@ -114,6 +128,8 @@ export function Example() {
followOutput={followOutput}
itemContent={virtosoItemContent}
data={channel.messages}
firstItemIndex={channel.firstItemIndex}
startReached={loadOlderMessages}
{...(channelState ? {} : { initialTopMostItemIndex: channel.messages.length - 1 })}
/>

Expand Down
15 changes: 10 additions & 5 deletions src/stateLoadSystem.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { domIOSystem } from './domIOSystem'
import { initialTopMostItemIndexSystem } from './initialTopMostItemIndexSystem'
import { StateSnapshot, StateCallback } from './interfaces'
import { propsReadySystem } from './propsReadySystem'
import { sizeSystem, sizeTreeToRanges } from './sizeSystem'
import * as u from './urx'

export const stateLoadSystem = u.system(([{ sizes, sizeRanges }, { scrollTop }, { initialTopMostItemIndex }]) => {
export const stateLoadSystem = u.system(([{ sizes, sizeRanges }, { scrollTop }, { initialTopMostItemIndex }, { didMount }]) => {
const getState = u.stream<StateCallback>()
const restoreStateFrom = u.statefulStream<StateSnapshot | undefined>(undefined)

Expand All @@ -17,9 +18,13 @@ export const stateLoadSystem = u.system(([{ sizes, sizeRanges }, { scrollTop },

u.connect(
u.pipe(
restoreStateFrom,
u.filter(u.isDefined),
u.map((snapshot) => snapshot!.ranges)
didMount,
u.withLatestFrom(restoreStateFrom),
u.filter(([, state]) => state !== undefined),
u.distinctUntilChanged(),
u.map(([, snapshot]) => {
return snapshot!.ranges
})
),
sizeRanges
)
Expand All @@ -28,7 +33,7 @@ export const stateLoadSystem = u.system(([{ sizes, sizeRanges }, { scrollTop },
getState,
restoreStateFrom,
}
}, u.tup(sizeSystem, domIOSystem, initialTopMostItemIndexSystem))
}, u.tup(sizeSystem, domIOSystem, initialTopMostItemIndexSystem, propsReadySystem))

function locationFromSnapshot(snapshot: StateSnapshot | undefined) {
return { offset: snapshot!.scrollTop, index: 0, align: 'start' }
Expand Down

0 comments on commit 315be28

Please sign in to comment.