-
Notifications
You must be signed in to change notification settings - Fork 26
WIP: Web support #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
WIP: Web support #16
Conversation
src/BidirectionalFlatList.tsx
Outdated
| behavior: animated ? 'smooth' : 'auto', | ||
| index: 0, | ||
| }); | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be switched to
const index = inverted ? 0 : vData.length - 1;
virtuosoRef.current?.scrollToIndex({
behavior: animated ? 'smooth' : 'auto',
index,
});There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks , I will check it out. Planning to publish beta on this next week :) Please let me know if you find more things.
PR needs some testing and some cleanup which will happen early next week :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried this out over the weekend and put some thoughts here
No hard feelings, but at the moment this web implementation is noticeably slower than the web implementation from react-native-web Flatlist
I've tried playing around with overscan but it doesn't seem to affect the issue
It looks like Virtuoso is the bottleneck though I'm not 100% certain
| "react-dom": "^17.0.2", | ||
| "react-native": "0.63.4", | ||
| "react-native-builder-bob": "^0.17.1", | ||
| "react-virtuoso": "^1.6.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
react-virtuoso should probably be listed in dependencies or peerDependencies
src/BidirectionalFlatList.tsx
Outdated
| () => ({ | ||
| flashScrollIndicators: () => null, | ||
| getNativeScrollRef: () => null, | ||
| getScrollableNode: () => null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can return scrollerRef.current - getScrollableNode: () => scrollerRef.current
Unfortunately it will be available on the 2nd render, so the parent component that uses BidirectionalFlatList won't have it during componentDidMount or useEffect(() => {}, [])
With the original FlatList getScrollableNode would return the node for componentDidMount
src/BidirectionalFlatList.tsx
Outdated
| <Virtuoso<T> | ||
| components={{ | ||
| Footer, | ||
| Header, | ||
| }} | ||
| firstItemIndex={firstItemIndex.current} | ||
| initialTopMostItemIndex={ | ||
| inverted | ||
| ? vData.length - 1 - initialScrollIndex | ||
| : initialScrollIndex | ||
| } | ||
| itemContent={itemContent} | ||
| onScroll={handleScroll} | ||
| overscan={300} | ||
| ref={virtuosoRef} | ||
| // @ts-ignore | ||
| scrollerRef={(ref) => (scrollerRef.current = ref)} | ||
| totalCount={vData.length} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This portion is pretty much repeated and can be extracted to a const
const VirtuozoNode = (
<Virtuoso<T>
components={{}}
...
/>
);
if (!onRefresh) {
return VirtuozoNode;
}
return (
<Animated.View>
<Animated.View>
<ActivityIndicator />
</Animated.View>
{VirtuozoNode}
</Animated.View>
)
src/BidirectionalFlatList.tsx
Outdated
| <View style={styles.indicatorContainer}> | ||
| <ActivityIndicator size={'small'} color={activityIndicatorColor} /> | ||
| </View> | ||
| <Virtuoso<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FlatList has getItemLayout prop to aid rendering
Virtuoso has itemSize but it's called with an html element: https://virtuoso.dev/virtuoso-api-reference/ (see itemSize)
I don't see a way to make use of getItemLayout with Virtuoso
FlatList.getItemLayout-> is called withdata, indexand returns{ length, offset, index }Virtuoso.itemSize-> is called withdomNodeand returns anumber(height or width of the item)- does this mean that Virtuoso have to first render the items and then update the size ?
For web it might be impossible to implement getItemLayout when Virtuoso is used for virtualization
Other libraries like react-virtual provide a compatible interface
You can do something like:
estimateSize = index => {
const size = props.getItemLayout(props.data, index);
return size.length;
}
src/BidirectionalFlatList.tsx
Outdated
| } | ||
| itemContent={itemContent} | ||
| onScroll={handleScroll} | ||
| overscan={300} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be something like
overscan={(scrollerRef.current?.offsetHeight * props.windowSize) || 300}As per https://reactnative.dev/docs/virtualizedlist#windowsize this is how many screens of data to pre-render
And per https://virtuoso.dev/virtuoso-api-reference/ overscan is in px
Not sure if windowSize has to be halved though
- for 21 react-native FlatList would add 10 pages up and 10 down
- would Virtuoso do the same or add 21 pages up and 21 pages down?
src/BidirectionalFlatList.tsx
Outdated
| }, [onRefresh]); | ||
|
|
||
| if (!vData?.length || vData?.length === 0) { | ||
| return <ListEmptyComponent />; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that this does not have a default and crashes when vData is empty
Perhaps it can just return null when ListEmptyComponent is not defined
or have a default ListEmptyComponent
| const startReached = async () => { | ||
| if ( | ||
| !onStartReached || | ||
| prependingItems.current || | ||
| onStartReachedInProgress || | ||
| (inverted && !onEndReached) || | ||
| (!inverted && !onStartReached) | ||
| ) { | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason both startReached and endReached are not always triggered, even when there is more data to be loaded
I think it has to do with the count of items rendered
For some chats scrolling to the past (on inverted list) triggers onEndReached and loads older messages, for others it isn't getting picked up
We're using an inverted list so that's where I've test the most, but I did swap it for non-inverted and it seemed it worked better
Hey @kidroca can you share some screen-recording? Just to understand !! |
…Stream/react-native-bidirectional-infinite-scroll into vishal/web-support-onrefresh
e685877 to
c1f1876
Compare
|
@vishalnarkhede do you plan to finish web support? Is this package still being developed? |
Uh oh!
There was an error while loading. Please reload this page.