简体   繁体   中英

How to solve Cannot read properties of undefined (reading 'length')? Paging using react, MUI and TypeScript

I'm developing code that aims to show a limited number of cards per page based on the amount of data stored in a JSON file. I expected that clicking on the ">" or "<" icon would go to the next or previous page respectively changing the cards.

My App.tsx looked like this:

import { default as data } from "./DATA.json" //contains an array of json objects.

let [page, setPage] = useState(1); //is a state that stores the beginning of pagination.

const PER_PAGE = 8; //stores how many cards will be displayed per page.

const totalPages= Math.ceil(data.length / PER_PAGE); //stores the total number of pages

import { usePagination } from "./Pagination"; 
//is a component that receives as parameter data and PER_PAGE. Inside the component there are 4 functions:

currentData(); //get current data from JSON
jump(); //jump to the next page
next(); //show the contents of the next page
prev(); //show the contents of the previous page

const _DATA = usePagination(data, PER_PAGE);

Ps: In the component usePagination.tsx I passed the DataBooks interface for the data and itemsPerPage parameters, however, the error Cannot read properties of undefined (reading 'length') appears. The result I wanted was not achieved (change cards accordingly as you go to the next or previous page) because I don't know what it is. Someone help me please I don't know what to do.

import { useState } from "react";
import Books from "./interfaces";

interface DataBooks {
  data: Books[];
  itemsPerPage: number;
}

export const usePagination = ({ data, itemsPerPage }: DataBooks) => {
  const [currentPage, setCurrentPage] = useState(1);
  const maxPage = Math.ceil(data.length / itemsPerPage);

  function currentData() {
    const begin = (currentPage - 1) * itemsPerPage;
    const end = begin + itemsPerPage;
    return data.slice(begin, end);
  }

  function next() {
    setCurrentPage((currentPage) => Math.min(currentPage + 1, maxPage));
  }

  function prev() {
    setCurrentPage((currentPage) => Math.max(currentPage - 1, 1));
  }

  function jump(page: number) {
    const pageNumber = Math.max(1, page);
    setCurrentPage((currentPage) => Math.min(pageNumber, maxPage));
  }
  return { next, prev, jump, currentData, currentPage, maxPage };
};

Code in codesanbox

UPDATE

Live demo of the project fixed: codesandbox

In App.tsx the Pagination component should be set like this:

<Pagination count={totalPages} page={page} onChange={handleChange} />

You don't need to manually pass event and page to this onChange function because MUI will handle these internally. More specifically, it pass to the function which page is being changed to instead of the the current page.

This is the main reason why the Pagination was not functioning. I changed the title of cards to item.title + "-" + item.id so you can check the live demo to see it works.

Syntax fixes

I fixed some syntax error so there is no error message about types.

Changes made in UsePagination.tsx

// Need to check if data is provided
const maxPage = data ? Math.ceil(data.length / itemsPerPage) : 1;

function currentData() {
  // Again this data may not be provided
  if (!data) return [];

  const begin = (currentPage - 1) * itemsPerPage;
  const end = begin + itemsPerPage;
  return data.slice(begin, end);
}

Changes made in App.tsx :

// This function take an object as argument
const _DATA = usePagination({ data, itemsPerPage: PER_PAGE });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM