I’m getting data from Django Rest API and React for Frontend, and I need to create the pagination with posts. I did it all in pagination component. I created the state with current page and I’m changing it by clicking on the page button in component like this:
const Paginator = () => { const [count, setCount] = useState(null); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(null); const [nextPage, setNextPage] = useState(null); const [previousPage, setPreviousPage] = useState(null); const [valid, setValid] = useState(false); useEffect(() => { fetch(`http://127.0.0.1:8000/api/software/?p=${currentPage}`) .then(response => response.json()) .then(data => { setCount(data.count); setTotalPages(data.total_pages) setNextPage(data.links.next); setPreviousPage(data.links.previous); setValid(true); }) }, [currentPage]); ... return ( <> { ... <PbStart style={style} totalPages={range(1, totalPages+1)} setCurrentPage={setCurrentPage} /> ... } </> ); }; const PagItem = ({key, handleClick, className, title, name }) => { return ( <li key={key} onClick={handleClick}> <Link to='/' className={className} title={`Go to page ${title}`}> {name} </Link> </li> ); }; const PbStart = ({ style, totalPages, setCurrentPage }) => { return ( ... {totalPages.map(p => ( <PagItem key={p} handleClick={() => setCurrentPage(p)} title={p} name={p} /> ))} ... ); };
And in posts component I don’t know how to change current page, or getting it from the paginaton component. I’ve written that like this:
const Softwares = () => { const [softwares, setSoftwares] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [valid, setValid] = useState(false); useEffect(() => { fetch(`http://127.0.0.1:8000/api/software/?p=${currentPage}`) .then(response => response.json()) .then(data => { setSoftwares(data.results); setValid(true); }) }, [currentPage]); return ( <> { ... {softwares.map(s => ( <Article key={s.id} pathname={s.id} title={s.title} image={s.image} pubdate={s.pub_date} icon={s.category.parent.img} categoryID={s.category.id} categoryName={s.category.name} dCount={s.counter} content={s.content} /> ))} ... } </> ); };
So, how to do that(get the current page from pagination component or another way)?
Answer
I think a Paginator’s job is only moving between pages and updating current page state. It should not be fetching data by itself, you can provide functionality to do extra work with props.
I haven’t tested this, but this might be a good starting point.
With the example below you’ll have a list of articles and then below it next and previous buttons.
In Softwares
, as you can see I am passing the same function for handling next and previous pages, you can refactor it to have one function like onPageMove
and call this function handleNext
and handlePrev
.
I added two separate functions if you have want to handle something different in either.
const Paginator = ({ total, // Required: Total records startPage = 1, // Start from page / initialize current page to limit = 30, // items per page onMoveNext = null, // function to call next page, onMovePrev = null, // function to call previous page }) => { const [currentPage, setCurrentPage] = useState(startPage); const canGoNext = total >= limit; const canGoPrev = currentPage > 1; function handleNext(e) { if (canGoNext) { setCurrentPage((prevState) => prevState+1); onMoveNext && onMoveNext({ currentPage }); } } function handlePrev(e) { if (canGoPrev) { setCurrentPage((prevState) => prevState-1); onMovePrev && onMovePrev({ currentPage }); } } return ( <div> <button onClick={handlePrev} disabled={!canGoPrev}>Prev</button> <button onClick={handleNext} disabled={!canGoNext}>Next</button> </div> ); };
Here is how you can use Paginator in other components.
const PER_PAGE = 30; // get max # of records per page const Softwares = () => { const [softwares, setSoftwares] = useState([]); const [valid, setValid] = useState(false); const onFetchData = ({ currentPage }) => { fetch(`http://127.0.0.1:8000/api/software/?p=${currentPage}&per_page=${PER_PAGE}`) .then(response => response.json()) .then(data => { setSoftwares(data.results); setValid(true); }) } useEffect(() => { onFetchData({ currentPage: 1 }) }, []); return ( <> {softwares.map(s => ( <Article key={s.id} pathname={s.id} title={s.title} image={s.image} pubdate={s.pub_date} icon={s.category.parent.img} categoryID={s.category.id} categoryName={s.category.name} dCount={s.counter} content={s.content} /> ))} <Paginator total={softwares.length} limit={PER_PAGE} onMoveNext={onFetchData} onMovePrev={onFetchData} /> </> ); };