skip to Main Content

I have a code where the moment I open a page I am setting a List Array this way:

const [myArray, updateArray] = useState([]);

useEffect(() => {

        var myItem= [...array1];

        if (state.pageNumber == 1 myItem= [...array2];
        else if (state.pageNumber == 2) myItem= [...array3]; 


        updateArray(myItem);

    }, []);

This works fine and the page is portraying the right array. The problem comes when I have to click a button and call the data on the updated array again. I have a function that when on click I have to read the array I updated. The problem is that "myArray" is coming up as blank. It only shows the data if the state changes for some reason like when I save my code again.

    const handleSelect = (selectedIndex) => {
        console.log(myArray);
    };

Above comes blank even after it correctly updated and displays correctly on the page.

2

Answers


  1. You could get the previous state and return it for the next state just by adding a callback.

    useEffect(() => {
         updateArray((array)=> [...(pageNumber === 1 ? array1 : pageNumber === 2 ? array2 : array)]);
    }, [pageNumber]);
    

    If you want to set a new array everytime pageNumber changes, you should set the pageNumber as the useEffect dependency.

    If you want to update the array everytime array1 and array2 changes, you should also add it to the useEffect dependency.

    useEffect(() => {
       //code
    }, [pageNumber, array1, array2]);
    

    Note: You should create a new copy of object or array every time you set a new state to re-render it.

    Login or Signup to reply.
  2. Here is an example of pagination in React using Redux Toolkit. Your component should know how to access the items from the Redux store, along with the current page size and page index.

    // Visible books
    const pagedBooks = useMemo(() => books.slice(startIndex, endIndex), [
      books,
      endIndex,
      startIndex
    ]);
    

    I exported the start index, end index, and page count calculation functions as well, since they will be needed outside of the pagination component.

    Full demo here: Codesandbox

    Package.json

    {
      "dependencies": {
        "@fortawesome/fontawesome-svg-core": "6.4.0",
        "@fortawesome/free-solid-svg-icons": "6.4.0",
        "@fortawesome/react-fontawesome": "0.2.0",
        "@reduxjs/toolkit": "1.9.3",
        "react": "18.2.0",
        "react-dom": "18.2.0",
        "react-redux": "8.0.5",
      }
    }
    

    Paginator.jsx

    import { useCallback, useMemo } from "react";
    import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
    import {
      faAngleDoubleLeft,
      faAngleDoubleRight,
      faAngleLeft,
      faAngleRight
    } from "@fortawesome/free-solid-svg-icons";
    
    const calcStartIndex = (pageSize, pageIndex) => pageSize * pageIndex;
    
    const calcEndIndex = (items, pageSize, startIndex) =>
      Math.min(startIndex + pageSize, items.length);
    
    const calcPageCount = (items, pageSize) =>
      Math.floor(items.length / pageSize) + Math.sign(items.length % pageSize);
    
    const Paginator = ({
      changeIndex,
      changePageSize,
      items,
      pageIndex,
      pageSize
    }) => {
      const pageCount = useMemo(() => calcPageCount(items, pageSize), [
        items,
        pageSize
      ]);
    
      const startIndex = useMemo(() => calcStartIndex(pageSize, pageIndex), [
        pageSize,
        pageIndex
      ]);
    
      const endIndex = useMemo(() => calcEndIndex(items, pageSize, startIndex), [
        items,
        pageSize,
        startIndex
      ]);
    
      const onPageSizeChange = useCallback((e) => changePageSize(+e.target.value), [
        changePageSize
      ]);
    
      const onFirstClick = useCallback(() => {
        changeIndex(0);
      }, [changeIndex]);
    
      const onPrevClick = useCallback(() => {
        changeIndex(pageIndex - 1);
      }, [changeIndex, pageIndex]);
    
      const onNextClick = useCallback(() => {
        changeIndex(pageIndex + 1);
      }, [changeIndex, pageIndex]);
    
      const onLastClick = useCallback(() => {
        changeIndex(pageCount - 1);
      }, [changeIndex, pageCount]);
    
      return (
        <div className="Paginator">
          <div className="pagination-col">
            <select
              value={pageSize}
              onChange={onPageSizeChange}
              title="Items per page"
            >
              <option value="2">2</option>
              <option value="5">5</option>
              <option value="10">10</option>
            </select>
          </div>
          <div className="pagination-col pagination-actions">
            <button
              type="button"
              className="pagination-btn"
              disabled={pageIndex <= 0}
              onClick={onFirstClick}
              title="Go to first page"
            >
              <FontAwesomeIcon icon={faAngleDoubleLeft} />
            </button>
            <button
              type="button"
              className="pagination-btn"
              disabled={pageIndex <= 0}
              onClick={onPrevClick}
              title="Go to previous page"
            >
              <FontAwesomeIcon icon={faAngleLeft} />
            </button>
            <div>
              Page {pageIndex + 1} of {pageCount}
            </div>
            <button
              type="button"
              className="pagination-btn"
              disabled={pageIndex >= pageCount - 1}
              onClick={onNextClick}
              title="Go to next page"
            >
              <FontAwesomeIcon icon={faAngleRight} />
            </button>
            <button
              type="button"
              className="pagination-btn"
              disabled={pageIndex >= pageCount - 1}
              onClick={onLastClick}
              title="Go to last page"
            >
              <FontAwesomeIcon icon={faAngleDoubleRight} />
            </button>
          </div>
          <div className="pagination-col">
            {startIndex + 1}–{endIndex} of {items.length}
          </div>
        </div>
      );
    };
    
    export default Paginator;
    
    export { calcEndIndex, calcPageCount, calcStartIndex };
    

    Usage

    import { useCallback, useEffect, useMemo, useState } from "react";
    import { useSelector, useDispatch } from "react-redux";
    import BookItem from "./BookItem";
    import Paginator, {
      calcEndIndex,
      calcPageCount,
      calcStartIndex
    } from "./Paginator";
    
    const LibraryView = () => {
      const { books } = useSelector((state) => state.library);
      const dispatch = useDispatch();
    
      const [pageIndex, setPageIndex] = useState(0);
      const [pageSize, setPageSize] = useState(5);
    
      useEffect(() => {
        const lastIndex = calcPageCount(books, pageSize) - 1;
        if (pageIndex > lastIndex) {
          setPageIndex(lastIndex);
        }
      }, [books, pageIndex, pageSize]);
    
      const startIndex = useMemo(() => calcStartIndex(pageSize, pageIndex), [
        pageSize,
        pageIndex
      ]);
    
      const endIndex = useMemo(() => calcEndIndex(books, pageSize, startIndex), [
        books,
        pageSize,
        startIndex
      ]);
    
      const pagedBooks = useMemo(() => books.slice(startIndex, endIndex), [
        books,
        endIndex,
        startIndex
      ]);
    
      const changeIndex = useCallback((newIndex) => setPageIndex(newIndex), []);
    
      const changePageSize = useCallback((newPageSize) => {
        setPageSize(newPageSize);
      }, []);
    
      return (
        <div className="LibraryView">
          <div className="Books">
            {pagedBooks.map((book) => (
              <BookItem key={book.isbn} {...book} />
            ))}
          </div>
          <Paginator
            changeIndex={changeIndex}
            changePageSize={changePageSize}
            items={books}
            pageIndex={pageIndex}
            pageSize={pageSize}
          />
        </div>
      );
    };
    
    export default LibraryView;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search