0
votes

So I’m having a little trouble on loading more items from the array. I already made it display the first four items, but when I click the Pagination items it doesn’t show me the next items. I’m using the Pagination component from React Bootstrap, since it’s the main framework of my project.

  const [pagination, setPagination] = useState({
    data: names,
    offset: 0,
    numberPerPage: 4,
    pageCount: 0,
    currentData: [],
    activePage: 1
  });

  useEffect(() => {
    setPagination((prevState) => ({
      ...prevState,
      pageCount: prevState.data.length / prevState.numberPerPage,
      currentData: prevState.data.slice(
        pagination.offset,
        pagination.offset + pagination.numberPerPage
      )
    }));
  }, [pagination.numberPerPage, pagination.offset]);

  const handlePageClick = (event) => {
    const selected = event.selected;
    const offset = selected * pagination.numberPerPage;
    const activePage = selected + 1;
    setPagination({ ...pagination, offset, activePage });
  };

  // Pagination items
  const paginationItems = [];
  const amountPages = pagination.data.length / pagination.numberPerPage;
  for (let number = 1; number <= amountPages; number++) {
    paginationItems.push(
      <Pagination.Item
        onClick={handlePageClick}
        key={number}
        active={number === pagination.activePage}
      >
        {number}
      </Pagination.Item>
    );
  }

  return (
    <div className="list">
      <Container>
        {pagination.currentData &&
          pagination.currentData.map((item, index) => (
            <div key={index} className="post">
              <h3>{item.name}</h3>
            </div>
          ))}

        <Pagination>{paginationItems}</Pagination>
      </Container>
    </div>
  );

Here is the codesandbox that I'm using for example: https://codesandbox.io/s/react-bootstrap-pagination-mp9l8?file=/src/App.js

1

1 Answers

1
votes

when you have an object as a state, you should change state with useReducer. first of all you should set Onclick on Pagination component instead of Pagonation.Item, also I set data-page attribute for each Pagination.Item for access that on handleClick function.

import React, { useReducer, useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Container, Pagination } from "react-bootstrap";

export default function App({ content }) {

  const reducer = (state, action) => {
    switch (action.type) {
      case "setPageCount":
        return { ...state, pageCount: action.payload };
      case "setCurrentData":
        return { ...state, currentData: action.payload };
      case "setOffset":
        return { ...state, offset: action.payload };
      case "setActivePage":
        return { ...state, activePage: action.payload };
      default:
        throw new Error();
    }
  };

  const initialState = {
    data: names,
    offset: 0,
    numberPerPage: 4,
    pageCount: 0,
    currentData: [],
    activePage: 1
  };

  const [state, dispatch] = useReducer(reducer, initialState);

  useEffect(() => {
    dispatch({
      type: "setCurrentData",
      payload: state.data.slice(
        state.offset,
        state.offset + state.numberPerPage
      )
    });
  }, [state.numberPerPage, state.offset]);

  const handleClick = (e) => {
    const clickValue = parseInt(e.target.getAttribute("data-page"), 10);
    dispatch({
      type: "setOffset",
      payload: (clickValue - 1) * state.numberPerPage
    });
    dispatch({
      type: "setActivePage",
      payload: clickValue
    });
    dispatch({
      type: "setPageCount",
      payload: state.data.length / state.numberPerPage
    });
  };

  // Pagination numbers
  const paginationItems = [];
  const amountPages = state.data.length / state.numberPerPage;
  for (let number = 1; number <= amountPages; number++) {
    paginationItems.push(
      <Pagination.Item
        key={number}
        active={number === state.activePage}
        data-page={number}
      >
        {number}
      </Pagination.Item>
    );
  }

  return (
    <div className="list">
      <Container>
        {state.currentData &&
          state.currentData.map((item, index) => (
            <div key={index} className="post">
              <h3>{item.name}</h3>
            </div>
          ))}

        <Pagination onClick={handleClick}>{paginationItems}</Pagination>
      </Container>
    </div>
  );
}

you can see how it's work HERE