0

I'm trying to turn a long list of objects (accounts) into smaller arrays of 6 or less. I'm doing this because I have a table in my react component that is listing all the accounts, however, it cannot hold any more than 6 accounts. I created the pagination and everything, and thought that it would work, but the current page doesn't ever seem to update.

const [pageNum, setPageNum] = useState(1);
const [numOfPages, setNumOfPages] = useState(Math.ceil(accounts.length / 6));
const [page, setPage] = useState([]);
const [pages, setPages] = useState([null]);

const onClick = (e) => {
    setPageNum(pageNum + 1);
    setPage(pages[pageNum]);
};

useEffect(() => {
    if (numOfPages > 1) {
        for (let i = 0; i < 6; i++) {
            setPages(pages.push(accounts.slice(i * 6, i * 6 + 6)));
        }
    }
    console.log(pages[1][1]);
    console.log(pages[2][2]);
    setPage([pages[1][1], pages[1][2]]);
    console.log(page);
}, []);

This isn't the final code, but rather part of my troubleshooting and I also think its where the issue is coming up. When I console log pages[1][1] and pages[1][2], I get two separate objects. So how come after using setPage and placing the two 'objects' inside of an array, does the console log of page come out as an empty array?? I've tried refactoring so many things. I've changed pages to an object instead of an array, i've tried doing it in another method instead of useEffect, all kinds of things. But the root of the issue seems to be that often my 'setPage' and my 'setPageNum' methods fail for seemingly no reason.

2 Answers 2

3

Prepare the pages array with useMemo (it will only change when accounts changes).

const { useState, useMemo, useCallback } = React;

const Pager = ({ accounts }) => {
  const [pageNum, setPageNum] = useState(0);

  const pages = useMemo(() => {
    const pages = [];

    for (let i = 0; i < accounts.length; i += 6) {
      pages.push(accounts.slice(i, i + 6));
    }

    return pages;
  }, [accounts]);
  
  // console.log(pages);

  const numOfPages = pages.length;

  const page = pages[pageNum];

  const next = useCallback(() => {
    setPageNum(pageNum => pageNum + 1);
  }, []);
  
  const prev = useCallback(() => {
    setPageNum(pageNum => pageNum - 1);
  }, []);
  
  return (
    <div>
      <button disabled={pageNum === 0} onClick={prev}>Prev</button>
      <button disabled={pageNum === numOfPages - 1} onClick={next}>Next</button>
      <ul>
        {pages[pageNum].map((s, i) => <li key={i}>{s}</li>)}
      </ul>
    </div>
  );
};

const accounts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];

ReactDOM.render(
  <Pager accounts={accounts} />,
  root
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

The main problem in your code is the way you use setPages:

setPages(pages.push(accounts.slice(i * 6, i * 6 + 6)));

The Array.push() returns the new length of the array. So your pages state is actually the last number. It's the last number because setState replaces the state, and doesn't add it.

Sign up to request clarification or add additional context in comments.

5 Comments

How am I able to set the page then? I tried using this variation, but it still won't let me set the page. const [page, setPage] = useState(pages[1]); console.log(page); console.log(pages); the console log of page in this case is still an empty array
You don't need to set the page. The page is derived from pages and pageNum page = pages[pageNum];.
You actually can do it. You are mapping an array because pages[0] is an array. Your problem is that your initial page is 1. Just change the initial state to 0.
You'll also need to handle the case where the page doesn't exist (no items)
I've updated with a working example - the error was in this line pages.push(accounts.slice(i, i + 6));. I've incremented i by 6, but left your original slice i * 6, i * 6 + 6.
2

The term you are looking for is chunk. Since the data you are chunking comes from props, you don't need chunk inside the useEffect hook. It's not a side effect.

Here is a chunk function I found on the internet:

function chunkArray(myArray, chunk_size){
    var index = 0;
    var arrayLength = myArray.length;
    var tempArray = [];

    for (index = 0; index < arrayLength; index += chunk_size) {
        myChunk = myArray.slice(index, index+chunk_size);
        // Do something if you want with the group
        tempArray.push(myChunk);
    }

    return tempArray;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.