Reputation: 65
I am building a web-app and I am also new with web-dev and all. I have backend-response as json with pagination in it, looks like that:
{
"count": 16,
"next": "http://localhost:8000/en/api/events/?page=3",
"previous": "http://localhost:8000/en/api/events/",
"results": [
{
"url": "",
"id": ,
"title": "",
"creation_date": "",
"description": "",
"event_date": "",
"link": ""
},
...
],
"total_pages": 4
}
And I want to add pagination to my EventList.jsx component:
import React, { useState, useEffect } from "react";
import { Link, NavLink } from "react-router-dom";
import "./Content.css";
import "./Pagination";
import { useLanguage } from "../../context/LanguageTranslator";
import { getLanguage } from "../../utils/getLanguage";
import Pagination from "./Pagination";
const initialState = {
fullAPI: {
count: 0,
next: null,
previous: null,
results: [],
total_pages: 0,
},
};
const EventList = (props) => {
const { language } = useLanguage();
const currentLanguage = getLanguage(language);
const [state, setState] = useState(initialState);
const [loading, setLoading] = useState(false);
useEffect(async () => {
try {
setLoading(true);
const langUrl = currentLanguage.urlName;
const page = props.match.params.page;
const defaultUrl = `http://localhost:8000/${langUrl}/api/events/?page=${page}`;
// * url which we will fetch
let currentUrl;
currentUrl = defaultUrl;
const res = await fetch(currentUrl);
const fullAPI = await res.json();
setState((prevState) => ({ ...prevState, fullAPI }));
setLoading(false);
} catch (error) {
setLoading(false);
console.log(error);
}
}, []);
const renderEvents = () => {
const eventsList = state.fullAPI.results;
return eventsList.map((item) => (
<li key={item.id}>
<p>
{currentLanguage.title}:{item.title}
</p>
<p>
<a href={item.link} className="aa">
{currentLanguage.organizers}
</a>
</p>
<Link to={`/events/id=${item.id}`} className="aa">
{currentLanguage.linkToEvent}
</Link>
</li>
));
};
return (
<main>
<div>
<ul>{renderEvents()}</ul>
<Pagination
totalPages={state.fullAPI.total_pages}
next={state.fullAPI.next}
previous={state.fullAPI.previous}
currentPage={props.page}
/>
</div>
</main>
);
};
export default EventList;
Basically now I have this Pagination.jsx:
import React, { useState, useEffect } from "react";
import { Link, NavLink, Redirect, useHistory } from "react-router-dom";
import "./Content.css";
import "./pagination.css";
const Pagination = (props) => {
// * pagination
const pages = [];
for (let i = 1; i <= props.totalPages; ++i) {
pages.push(i);
}
const handleClick = (number) => {
return `/events/page=${number}`;
};
const renderPageNumbers = pages.map((number) => {
return (
<li
key={number}
id={number}
onClick={() => {
window.location.href = handleClick(number);
}}
>
{number}
</li>
);
});
return (
<div>
{props.currentPage}
<ul className="pageNumbers">{renderPageNumbers}</ul>
</div>
);
};
export default Pagination;
A coded it this way because I needed to reload page in order to fetch a response from server. So now I reload page and have no ability to store state inside the Pagination component and can't do things like this: [frist] [prev] 1 [2] ... 9 10 [next] [last]
only this: 1 2 3 4 5 6 7 8 9 10
Upvotes: 1
Views: 335
Reputation: 1881
You should not only fetch a response from the server on page load. You can initially fetch on page load, but loading from the server should be in a separate function that's both called from within useEffect
as well as when the user wants to go to the next or previous page.
As for the [first] [prev] kind of thing, you'll need to add separate elements for that. You're currently creating an array of every page--instead you probably just want to have individual elements for [first]
[prev]
, [n-2]
through [n+2]
, [next]
, and [last]
. I notice your response has next
and previous
links, but, if possible, you're probably better off just sending the current page and then fetching the previous or next page number yourself (since you already know the endpoint to hit).
Anyway, I did my best, it didn't seem like you gave a specific question so I tried to answer what it looks like you were having trouble with.
Upvotes: 1