1

I have data which I populated from the network tab of an ecommerce website, if I have the data of 20 pages in one "data.json" file, how do I make it such so that one page displays first 20 items, the next page shows the next 20 items?

  • Keep track of a `page` and `rowsPerPage` variable. Slice the data array like this: `data.slice((page - 1) * rowsPerPage, page * rowsPerPage)`. If the number of rows is constant, you don't need a state variable, and can just hardcode it. – Arno van Liere Dec 19 '21 at 11:49
  • 1
    Does this answer your question? [How to implement pagination in React](https://stackoverflow.com/questions/40232847/how-to-implement-pagination-in-react) – Nikita Skrebets Dec 25 '21 at 20:16

1 Answers1

0

First I would create some IIFE curried function which first loads data.json file and returns function which paginates data.

const getPagedItems = (() => {
  const allItemsPromise = loadDataJson();

  return (page, pageSize) => {
    return allItemsPromise.then(allItems => {
      const it = page * pageSize;
      const items = allItems.slice(it, it + pageSize);

      return {
        items,
        totalCount: allItems.length
      }
    });
  }
})();

As for the component structure, I would create List component for rendering items and Paginator component for traversing items, setting items per page etc.

Or import some 3rd part component which handles these things like MUI React Table

<Page>
    <List items={items} />
    <Paginator
       page={page}
       totalPages={totalPages}
       itemsPerPage={itemsPerPage}
       onSelectPage={onSelectPage}
       onSelectItemsPerPage={onSelectItemsPerPage} />
</Page>

Example

const { useState, useEffect } = React;

const itemsPerPageList = [5, 10];

// data.json
const getAllItems = () => Promise.resolve(Array(23).fill(0).map((pr, index) => ({
  id: index,
  name: `Item ${index + 1}`
})));

const getPagedItems = (() => {
  const allItemsPromise = getAllItems();

  return (page, pageSize) => {
    return allItemsPromise.then(allItems => {
      const it = page * pageSize;
      const items = allItems.slice(it, it + pageSize);

      return {
        items,
        totalCount: allItems.length
      }
    });
  }
})();

const List = ({
items,
}) => {
  return <div>
    {items.map(pr => <div key={pr.id}>{pr.name}</div>)}
  </div>
}

const Paginator = ({
  itemsPerPage,
  page,
  totalPages,
  onSelectPage,
  onSelectItemsPerPage
}) => {
  const _onSelectPage = (event) => {
    const page = Number(event.currentTarget.dataset.page);
    onSelectPage(page);
  }
  
  const _onSelectItemsPerPage = (event) => {
    const page = Number(event.currentTarget.value);
    onSelectItemsPerPage(page);
  }

  return <div className="paginator">
    <div>Items per page</div>
    <select onChange={_onSelectItemsPerPage}>
      {itemsPerPageList.map(pr => <option key={pr} value={pr}>{pr}</option>)}
    </select>
    <div>Page {page} of {totalPages}</div>
    <button
      data-page={page - 1}
      disabled={!page}
      onClick={_onSelectPage}
      type="button">Previous</button>
    <button
      data-page={page + 1}
      disabled={page === totalPages}
      onClick={_onSelectPage}
      type="button">Next</button>
  </div>
}

const App = () => {
  const [{
    items,
    page,
    totalPages,
    itemsPerPage
  }, setState] = useState({
    items: [],
    page: 0,
    totalPages,
    itemsPerPage: 5,
  });
  
  useEffect(() => {
    let unmounted = false;
  
    getPagedItems(page, itemsPerPage).then(result => {
      const totalPages = Math.floor(result.totalCount / itemsPerPage);
    
    if(unmounted) {
      return;
    }
    
    setState(state => ({
      ...state,
      items: result.items,
      totalPages,
    }));
    });
    
    return () => unmounted = true;
    
  }, []);
  
  const onSelectPage = (page) => {
    getPagedItems(page, itemsPerPage)
    .then(result => {
      setState(state => ({
        ...state,
        page,
        items: result.items,
      }));
    })
  }
  
  const onSelectItemsPerPage = (itemsPerPage) => {
    const page = 0;
    getPagedItems(page, itemsPerPage)
    .then(result => {
      const totalPages = Math.floor(result.totalCount / itemsPerPage);

      setState(state => ({
        ...state,
        page,
        items: result.items,
        itemsPerPage,
        totalPages,
      }));
    })
  }

  return <div>
   <List items={items}/>
   <Paginator
    page={page}
    totalPages={totalPages}
    itemsPerPage={itemsPerPage}
    onSelectPage={onSelectPage}
    onSelectItemsPerPage={onSelectItemsPerPage}
   />
  </div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
.paginator {
  display: flex;
  justify-content: space-around;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
Józef Podlecki
  • 10,453
  • 5
  • 24
  • 50