AdeleD / react-paginate

A ReactJS component that creates a pagination

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to update/reset the pagination every time I search in the search bar for list item?

graydirt opened this issue · comments

commented

First I'm not sure if the functionality of my filter/search bar are correct.

Here are my concern, we have the words 'dolor' and 'dolorum' in the items of 25pages.

You can view it here.

Try to search the word "dolor" in the searchbar, the 25pages pagination is now 18pages. Then click the third pagination links and update your search to 'dolorum' in the searchbar, see the message says 'No Posts Found!' and the pagination is now 2pages. But we have 'dolorum' content in the items but it is only up to two pages of the pagination, and I think that is the reason why I got an error of 'No Posts Found!', because I clicked the third pagination links.

Is my code/functionality right? Is there any suggestions to avoid that bug in my code? maybe update the pagination/content items everytime I search?

Below is my code and to better understand here is the complete sandbox code https://codesandbox.io/. It's free to fork it!

Movielist.js

import { React, useState, useEffect } from "react";
import MovieListPagination from "./MovieListPagination";
import SearchBar from "./SearchBar";

const MovieList = () => {
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [items, setItems] = useState([]);
  const [searchResults, setSearchResults] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setItems(result);
          setSearchResults(result);
          //console.log(result);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  }, []);

  if (error) {
    return <div className="p-3">Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div className="p-3">Loading...</div>;
  } else {
    return (
      <>
        <SearchBar items={items} setSearchResults={setSearchResults} />
        <MovieListPagination dataProps={searchResults} itemsPerPage={4} />
      </>
    );
  }
};

export default MovieList;

MovielistPagination.js

import { React, useState } from "react";
import { Row, Alert } from "react-bootstrap";
import ReactPaginate from "react-paginate";
import MovieListItems from "./MovieListItems";

const MovieListPagination = ({ itemsPerPage, dataProps }) => {
  const [itemOffset, setItemOffset] = useState(0);
  const endOffset = itemOffset + itemsPerPage;
  const currentItems = dataProps.slice(itemOffset, endOffset);
  const pageCount = Math.ceil(dataProps.length / itemsPerPage);
  const handlePageClick = (event) => {
    const newOffset = (event.selected * itemsPerPage) % dataProps.length;
    setItemOffset(newOffset);
  };

  const results = currentItems.map((item) => (
    <MovieListItems key={item.id} items={item} />
  ));

  const content = results?.length ? (
    results
  ) : (
    <Alert variant="primary">No Posts Found!</Alert>
  );

  return (
    <>
      <Row className="justify-content-center">{content}</Row>

      <ReactPaginate
        breakLabel="..."
        nextLabel="›"
        onPageChange={handlePageClick}
        pageRangeDisplayed={3}
        marginPagesDisplayed={1}
        pageCount={pageCount}
        previousLabel="‹"
        renderOnZeroPageCount={null}
        containerClassName="justify-content-center pagination"
        previousClassName="page-item"
        previousLinkClassName="page-link"
        nextClassName="page-item"
        nextLinkClassName="page-link"
        pageClassName="page-item"
        pageLinkClassName="page-link"
        breakClassName="page-item"
        breakLinkClassName="page-link"
        activeClassName="active"
        disabledClassName="disabled"
      />
    </>
  );
};

export default MovieListPagination;

SearchBar.js

import { Form, Button } from "react-bootstrap";

const SearchBar = ({ items, setSearchResults }) => {
  const handleSubmit = (e) => e.preventDefault();

  const handleSearchChange = (e) => {
    if (!e.target.value) return setSearchResults(items);

    const resultsArray = items.filter(
      (item) =>
        item.title.includes(e.target.value.toLowerCase()) ||
        item.body.includes(e.target.value.toLowerCase())
    );

    setSearchResults(resultsArray);
  };

  return (
    <>
      <Form onSubmit={handleSubmit}>
        <Form.Group className="my-3">
          <Form.Control
            type="text"
            id="search"
            placeholder="Search here..."
            onChange={handleSearchChange}
          />
        </Form.Group>
      </Form>
    </>
  );
};
export default SearchBar;

hello, @graydirt i am facing the same issue as you mentioned please share me solution regarding issue if you found any

@graydirt, firstly it should not work like that . if you are at page 1 then while searching it should those data which are in page 1 .it should not search for next page.

Please do let me know, if you need any assistance

commented

@graydirt, firstly it should not work like that . if you are at page 1 then while searching it should those data which are in page 1 .it should not search for next page.

Please do let me know, if you need any assistance

@Chandan9898Kumar correct me if I'm wrong, so you mean my code/functionality is right? Is there any suggestions to avoid that I call bug in my code?:) maybe update the pagination/content items everytime I search?

@graydirt just suppose if we have pagination and have 10 pages. So at page 1 we want show only 10 elements from index 0 to 10 and at page 2 we show elements from index 10 to 20 and so on.

ex- const [data,setData]=useState([] Here we are having 100 Datas

const [pageno,setPageNo] =useState(1) this is our current page no.

const paginatedData=data.slice(pageno10-10,pageno10).map((item)=>{
return(
your items to be shown here
)

})

now if i click on page 1 then i will get 10 elements only and will search only in these 10 elements.

I hope this will help you. Please do let know if you need any other help.

Thank you.

Screenshot from 2023-04-25 10-02-54
@graydirt you can solve this search issue by giving key prop to reactPaginate component as pageCount changes it will reset to first page, hope it helps, it's a work around way but it works in your given code sandbox example.
Also if you find any other solution let me know

commented

@graydirt just suppose if we have pagination and have 10 pages. So at page 1 we want show only 10 elements from index 0 to 10 and at page 2 we show elements from index 10 to 20 and so on.

ex- const [data,setData]=useState([] Here we are having 100 Datas

const [pageno,setPageNo] =useState(1) this is our current page no.

const paginatedData=data.slice(pageno_10-10,pageno_10).map((item)=>{ return( your items to be shown here )

})

now if i click on page 1 then i will get 10 elements only and will search only in these 10 elements.

I hope this will help you. Please do let know if you need any other help.

Thank you.

@Chandan9898Kumar Im just following your instructions, but Im confused:), can you fork my codesandbox link if its ok to you:)

commented

Screenshot from 2023-04-25 10-02-54 @graydirt you can solve this search issue by giving key prop to reactPaginate component as pageCount changes it will reset to first page, hope it helps, it's a work around way but it works in your given code sandbox example. Also if you find any other solution let me know

@MihirModi1421 hmm I added the key={pageCount}, but its not working, feel free to fork my codesandbox link..thx

@graydirt Just worked on your issue - here is the solution. please do let me know if you were seeking this solution.

import { React, useState, useEffect } from "react";
import MovieListPagination from "./MovieListPagination";
import SearchBar from "./SearchBar";

const MovieList = () => {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [items, setItems] = useState([]);
const [searchResults, setSearchResults] = useState([]);

useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((res) => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result);
setSearchResults(result);
//console.log(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
);
}, []);

if (error) {
return

Error: {error.message}
;
} else if (!isLoaded) {
return
Loading...
;
} else {
return (
<>


</>
);
}
};

export default MovieList;

@graydirt You have to set key={searchResults.length} on your MovieListPagination component.

https://65qqxe.csb.app

commented

It's working, I'm going to close this one. Thanks guys!