У меня есть этот список продуктов в магазине 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" (Загрузить больше) внизу этой страницы: https://www.markferragens.com.br/categoria/ferragens

0
Danilo Cunha 1 Сен 2020 в 22:49

2 ответа

Лучший ответ

Попробуйте установить позицию прокрутки в 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".

1
Patrick Fisher 1 Сен 2020 в 22:24

Что вы можете сделать, так это сохранить значение const savedHeight = document.body.offsetHeight, которое представляет собой полную высоту документа. Затем, после загрузки продуктов, установите window.scrollTo(0, savedHeight), так как тело, похоже, отвечает за прокрутку на вашей странице. Это заставит экран оставаться на том же месте, что и при нажатии кнопки загрузки.

0
Gabriel Petersson 1 Сен 2020 в 20:15