use rc-virtual-list

This commit is contained in:
srgooglo 2022-03-14 22:57:53 +01:00
parent c0ada28b7a
commit 9aceb9bc8a
2 changed files with 87 additions and 53 deletions

View File

@ -1,85 +1,100 @@
import React from "react" import React from "react"
import * as antd from "antd" import * as antd from "antd"
import { PostCard, PostCreator } from "components" import { PostCard } from "components"
import { InfiniteScroll } from "antd-mobile"
import List from "rc-virtual-list"
import "./index.less" import "./index.less"
export default class PostsFeed extends React.Component { export default class PostsFeed extends React.Component {
state = { state = {
loading: true, initialLoading: true,
skipStep: 0, list: [],
lastLength: 0, animating: false,
posts: [],
} }
api = window.app.request api = window.app.request
listRef = React.createRef()
componentDidMount = async () => { componentDidMount = async () => {
this.toogleLoading(true) await this.loadPosts()
await this.fetchPosts() window.app.ws.listen(`new.post`, async (data) => {
this.onInsert(data)
window.app.ws.listen(`new.post`, (data) => {
this.addPost(data)
}) })
this.toogleLoading(false) await this.setState({
} initialLoading: false,
toogleLoading = (to) => {
this.setState({ loading: to ?? !this.state.loading })
}
addPost = (post) => {
this.setState({
posts: [post, ...this.state.posts],
}) })
} }
fetchPosts = async () => { loadPosts = async ({
const posts = await this.api.get.feed(undefined, { startIndex,
stopIndex,
} = {}) => {
const result = await this.api.get.feed(undefined, {
startIndex,
stopIndex,
feedLength: this.props.feedLength,
user_id: this.props.fromUserId, user_id: this.props.fromUserId,
feedSkip: this.state.skipStep,
}).catch(error => {
console.error(error)
antd.message.error(error)
return false
}) })
if (posts) { console.log(result)
console.log(posts)
this.setState({ posts: [...posts, ...this.state.posts,], lastLength: posts.length }) if (result) {
this.setState({ list: result })
} }
} }
hasMore = () => { onAppear = (...args) => {
return this.state.posts.length < this.state.lastLength console.log('Appear:', args)
this.setState({ animating: false })
} }
loadMore = async () => { lockForAnimation = () => {
await this.setState({ skipStep: this.state.skipStep + 1 }) this.setState({ animating: true })
await this.fetchPosts() }
onInsert = async (data) => {
const updatedList = this.state.list
updatedList.unshift(data)
await this.setState({
list: updatedList,
})
this.lockForAnimation()
} }
render() { render() {
if (this.state.loading) { if (this.state.initialLoading) {
return <antd.Skeleton active /> return <antd.Skeleton active />
} }
if (this.state.list.length === 0) {
return <antd.Empty />
}
return <div className="postsFeed"> return <div
<div className="wrapper"> className="postsFeed"
{ >
this.state.posts.map(post => { <List
return <PostCard data={post} /> ref={this.listRef}
}) data={this.state.list}
} height="80vh"
itemHeight="100%"
<InfiniteScroll loadMore={this.loadMore} hasMore={this.hasMore} > className="content"
<div>Loading more...</div> >
</InfiniteScroll> {(item, index) => (
</div> <PostCard
data={item}
motionAppear={this.state.animating && index === 0}
onAppear={this.onAppear}
/>
)}
</List>
</div> </div>
} }
} }

View File

@ -6,7 +6,9 @@
width: 100%; width: 100%;
.wrapper { .content {
overflow: visible;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
align-items : center; align-items : center;
@ -15,8 +17,25 @@
width : 100%; width : 100%;
max-width: 40vw; max-width: 40vw;
>div { .rc-virtual-list-holder {
margin-bottom: 15px; overflow-y: visible !important;
width : 100%;
}
.rc-virtual-list-holder-inner {
width : 100%;
overflow: visible;
display : flex;
flex-direction : column;
align-items : center;
justify-content: center;
>div {
width : 100%;
margin-bottom: 15px;
}
} }
} }
} }