Ответы пользователя по тегу React
  • Как правильно хранить данные и создавать новые блоки без перерисовки всего компонента при скролле?

    liaFcipE
    @liaFcipE
    В общем виде, я бы делал как-то так:

    const LIMIT = 10;
    
    const getProducts = async (offset, limit) => { ... }
    
    function App () {
      const [offset, setOffset] = useState(0);
      const [products, setProducts] = useState([])
    
      useEffect(() => {
        getProducts(offset, LIMIT).then(products => setProducts(v => [...v, ...products]))
      }, [offset]);
    
      return <RenderProducts onScroll={() => { // increment offset }} />
    }


    Конечно, ваш бекенд должен уметь отдавать данные по limit & offset.
    И лучше вынести всю работу с данными в стор, тогда не нужен будет уродливый useEffect.

    Что-то вроде (nanostores):

    // store.ts
    const LIMIT = 30;
    
    export const $products = map({
      offset: 0,
      products: [],
      isLoading: true
    })
    
    onMount($products, () => {
      fetchProducts()
    })
    
    const fetchProducts = action($products, "fetchProducts", async store => {
      const { products, offset } = store.get();
    
      // TODO: add error handling
      store.setKey("isLoading", true);
      const newPartOfProducts = await api.getProducts(offset, LIMIT);
      store.setKey("products", [...products, ...newPartOfProducts ]);
      store.setKey("isLoading", false);
    });
    
    const incrementOffset = action($products, "incrementOffset", store => {
      const { offset } = store.get();
      store.setKey("offset", offset + LIMIT);
      fetchProducts()
    })
    
    export const $productsMutations = { incrementOffset }
    
    // App.tsx
    
    function App () {
      const { isLoading, products } = useStore($products)
    
      return (
        <Fragment>
          <RenderProducts onScroll={$productsMutations.incrementOffset} products={products} />
          {isLoading && <LoadingIndicator />}
        </Fragment>
      )
    }
    Ответ написан
    6 комментариев