添加新项目时如何使用无限滚动更新项目列表
How to update list of items with Infinite scroll when new item added
我在 React.js 上实现了无限滚动
这是我的无限滚动组件,它工作正常。
import React, {useRef,useCallback} from 'react';
function InfiniteScrollContainer(props) {
let {children,loadMore,hasMoreItems,classes} = props;
const observer = useRef()
const bottomRef = useCallback(node => {
if (observer.current) observer.current.disconnect()
observer.current = new IntersectionObserver(entries => {
if (entries[0].isIntersecting && hasMoreItems) {
loadMore()
}
})
if (node) observer.current.observe(node)
}, [hasMoreItems, loadMore]);
return(
<div>
<div className={classes}>
{children}
</div>
{hasMoreItems && <div className="load-more__container" ref={bottomRef}>
<span>Loading</span>
<div className="load-more-anim">
<div className="circle"/>
<div className="circle"/>
<div className="circle"/>
</div>
</div>}
{!hasMoreItems && <div className="load-more__container">No more data</div>}
</div>
)
}
export default InfiniteScrollContainer;
这是我的功能,我在其中请求获取更多数据
loadMoreResources = () => {
let {page,resources} = this.state;
let newPage = page +1;
this.setState({page: newPage})
this.props.getResources(undefined,undefined,newPage).then((res) => {
if(res.meta && (res.meta.current_page < res.meta.last_page)){
this.setState({hasMoreItems:true})
}else this.setState({hasMoreItems:false})
this.setState({
resources: [...resources,...res.data]
})
})
}
当我删除一个项目时,我只是通过 ID 从状态中删除了这个项目。它正在工作,但问题是当我创建新项目时,我需要更新项目列表。最好的方法是什么?
在服务器上我有一个分页并得到一个列表 {data:[], current_page:1, last_page:3, total_items:20}
我可以在状态下推送新项目。但是如何避免相同项目的重复?
如果您知道需要将它添加到数组中的什么位置,您可以更新状态,这与您在获取数据时所做的非常相似
this.setState({
resources: [newItem,...this.state.resources]
})
如果您要添加到顶部并且您的服务器再次返回相同的项目,您可以尝试对这两个项目使用相同的 key prop。如果它们都有相同的键,React 将不会渲染它们两次
您可以像这样更新 loadMoreResources 函数以从状态中删除所有重复项。
loadMoreResources = () => {
let {page,resources} = this.state;
let newPage = page +1;
this.setState({page: newPage})
this.props.getResources(undefined,undefined,newPage).then((res) => {
let ids = res.data.map(o => o.id)
let stateWithoutDuplicates = resources.filter(({id}) => !ids.includes(id))
if(res.meta && (res.meta.current_page < res.meta.last_page)){
this.setState({hasMoreItems:true})
}else this.setState({hasMoreItems:false})
this.setState({
resources: [...stateWithoutDuplicates,...res.data]
})
})
}
我在 React.js 上实现了无限滚动 这是我的无限滚动组件,它工作正常。
import React, {useRef,useCallback} from 'react';
function InfiniteScrollContainer(props) {
let {children,loadMore,hasMoreItems,classes} = props;
const observer = useRef()
const bottomRef = useCallback(node => {
if (observer.current) observer.current.disconnect()
observer.current = new IntersectionObserver(entries => {
if (entries[0].isIntersecting && hasMoreItems) {
loadMore()
}
})
if (node) observer.current.observe(node)
}, [hasMoreItems, loadMore]);
return(
<div>
<div className={classes}>
{children}
</div>
{hasMoreItems && <div className="load-more__container" ref={bottomRef}>
<span>Loading</span>
<div className="load-more-anim">
<div className="circle"/>
<div className="circle"/>
<div className="circle"/>
</div>
</div>}
{!hasMoreItems && <div className="load-more__container">No more data</div>}
</div>
)
}
export default InfiniteScrollContainer;
loadMoreResources = () => {
let {page,resources} = this.state;
let newPage = page +1;
this.setState({page: newPage})
this.props.getResources(undefined,undefined,newPage).then((res) => {
if(res.meta && (res.meta.current_page < res.meta.last_page)){
this.setState({hasMoreItems:true})
}else this.setState({hasMoreItems:false})
this.setState({
resources: [...resources,...res.data]
})
})
}
当我删除一个项目时,我只是通过 ID 从状态中删除了这个项目。它正在工作,但问题是当我创建新项目时,我需要更新项目列表。最好的方法是什么?
在服务器上我有一个分页并得到一个列表 {data:[], current_page:1, last_page:3, total_items:20}
我可以在状态下推送新项目。但是如何避免相同项目的重复?
如果您知道需要将它添加到数组中的什么位置,您可以更新状态,这与您在获取数据时所做的非常相似
this.setState({
resources: [newItem,...this.state.resources]
})
如果您要添加到顶部并且您的服务器再次返回相同的项目,您可以尝试对这两个项目使用相同的 key prop。如果它们都有相同的键,React 将不会渲染它们两次
您可以像这样更新 loadMoreResources 函数以从状态中删除所有重复项。
loadMoreResources = () => {
let {page,resources} = this.state;
let newPage = page +1;
this.setState({page: newPage})
this.props.getResources(undefined,undefined,newPage).then((res) => {
let ids = res.data.map(o => o.id)
let stateWithoutDuplicates = resources.filter(({id}) => !ids.includes(id))
if(res.meta && (res.meta.current_page < res.meta.last_page)){
this.setState({hasMoreItems:true})
}else this.setState({hasMoreItems:false})
this.setState({
resources: [...stateWithoutDuplicates,...res.data]
})
})
}