Reputation:
I have a component that performs a pagination feature with blog posts. Each time the "load more" button is clicked, five more posts are loaded to the bottom of the page. I am drawing a blank right now on how to solve an issue with it though.
The Problem:
Once the "load more" button is clicked and all of the available posts are visible, the "load more" button should go away.
The Code:
const Posts = ({ state }) => {
const [categories, setCategories] = useState([]);
const [categoryId, setCategoryId] = useState();
const [page, setPage] = useState(1);
const [posts, setPosts] = useState([]); // Posts for each category
const [allPosts, setAllPosts] = useState([]); // All posts from all categories
// Get all of the available categories
useEffect(() => {
fetch(state.source.api + "/wp/v2/categories")
.then(response => response.json())
.then(data => {
setCategories(data);
})
}, []);
useEffect(() => {
if (categoryId) {
fetch(state.source.api + "/wp/v2/posts?categories=" + categoryId + "&per_page=5")
.then((response) => response.json())
.then((data) => {
setPosts(data);
});
}
}, [categoryId]);
// Get posts for each category
useEffect(() => {
if (!categoryId) {
return;
}
let url = state.source.api + "/wp/v2/posts?categories=" + categoryId + "&per_page=5";
if (page > 1) {
url += `&page=${page}`;
}
fetch(url)
.then((response) => response.json())
.then((data) => {
setPosts([...posts, ...data]);
});
}, [categoryId, page]);
useEffect(() => {
let url = state.source.api + "/wp/v2/posts?per_page=5";
if (page > 1) {
url += `&page=${page}`;
}
fetch(url)
.then((response) => response.json())
.then((data) => {
setAllPosts([...allPosts, ...data]);
});
}, [page]);
// Add View All button to category buttons array
const allCategories = categories.map((category, i) => (category))
allCategories.push("View All");
return (
<>
{allCategories.map((category, i) => {
return (
(category === "View All") ? (
<button onClick={() => { setPosts([]) }}>View All</button>
) : (
<button className="btn" key={i} onClick={() => {
setPage(1);
setPosts([]);
setCategoryId(category.id);
}}>{category.name}</button>
)
)
})}
<div>
{posts.length === 0 ? (
<>
{allPosts.map((allPost, i) => {
return (
<li key={i}>{allPost.title.rendered}</li>
)
})}
<button onClick={() => { setPage(page + 1); }}>Load more</button>
</>
) : (
<>
<ol>
{posts.map((post, i) => {
return (
<li key={i}>{post.title.rendered}</li>
)
})}
</ol>
<button onClick={() => { setPage(page + 1); }}>Load more</button>
</>
)}
</div>
</>
)
}
Say there are a maximum of 3 pages worth of posts, five being viewed at a time - so 15 posts total... once all 3 pages are visible, and I click "load more" again (even though no more posts are available), I get a console error that ... my api... GET /wp/v2/posts?categories=78&per_page=5&page=4 400 (Bad Request)
, which obviously means that there was no page 4 to fetch because there are no more posts.
I think this requires an if statement, but I am not sure how I would get started writing it. Does anyone have any input?
Upvotes: 0
Views: 83
Reputation: 11
Try an npm package called "react-paginate", with this you can easily implement the pagination logic without messing up with the code, and here is the link for this package https://www.npmjs.com/package/react-paginate Just go with the documentation and you can figure out how to do this, but if you face any problem then don't hesitate, just ask me.
Upvotes: 0
Reputation: 725
You should have a variable called totalPages, which hold the number of pages, and then compare between totalPages and page states, something like that:
{page <= totalPages && <button onClick={() => { setPage(page + 1); }}>Load more</button>}
in this case if page is 3 and totalPages is 4 the button will not display
Upvotes: 1