如何解决当在ReactJS上的列表中合并更多项目时保持滚动位置
我在ReactJS商店中有以下产品列表:
{productsList.map((product) => (
<ProductItem
product={product}
/>
)}
当我在此列表中添加更多产品时,滚动位置移至列表末尾。添加更多产品的代码:
function nextPage() {
getMoreProducts().then((newProducts)=> {
setProductsList(productsList.concat(newProducts))
})
}
我需要保持滚动位置,因为这种方式,用户必须滚动到顶部才能看到加载的新产品。
我尝试存储滚动位置,但是更改是在列表增长之前完成的,所以什么也没发生:
function nextPage() {
const actualScrollPosition = window.pageYOffset
getMoreProducts().then((newProducts)=> {
setProductsList(productsList.concat(newProducts)) //<- setState from React is async.
window.scroll({ top: actualScrollPosition,behavior: "smooth" });
})
}
您可以单击此页面底部的橙色按钮“ Carregar mais”(加载更多)来检查此示例:cygwin-developers
解决方法
尝试在useLayoutEffect
更改触发的productsList
中设置滚动位置:
import React from 'react'
type Product = {
name: string
}
const getMoreProducts = async () => ([{name:'foo'}])
export const ProductItem: React.FC<{ product: Product> = ({ product }) => {
return <div>{product.name}</div>
}
export const ProductList: React.FC = () => {
const [productsList,setProductsList] = React.useState([])
let pageYOffset = window.pageYOffset
function nextPage() {
getMoreProducts().then((newProducts)=> {
pageYOffset = window.pageYOffset
setProductsList(productsList.concat(newProducts))
})
}
React.useEffect(() => {
window.scroll({ top: pageYOffset });
},[productsList])
return (
<>
{productsList.map((product) => (
<ProductItem
product={product}
/>
))}
<button onClick={nextPage}>Load more</button>
</>
)
}
在这种情况下,您也不需要behavior: "smooth"
。
您可以做的是保存const savedHeight = document.body.offsetHeight
值,即整个文档的高度。然后,在装入产品后,设置window.scrollTo(0,savedHeight)
,因为似乎页面的滚动由body负责。这将使屏幕停留在与单击加载按钮时相同的位置。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。