Why am I getting this problem?
When you use React‑Router DOM to handle pagination, you typically change either the route parameter (e.g. /posts/2) or the query string (e.g. /posts?page=2). If your component doesn’t react to that change, it will keep showing the old page. Common reasons:
1. No dependency on the page value in your effect
You fetch data in useEffect but forgot to include the page parameter in the dependency array, so it only runs once.
2. Using the same component instance
React‑Router by default reuses the component when only URL search params change, so componentDidMount/first useEffect fires once.
3. Reading the wrong param
Mixing up route params (useParams) with query params (useLocation + URLSearchParams) means you never pick up the new page number.
Solution
Below is a simple example using query params (?page=2) with React‑Router v6. We break it into small parts:
- Set up routes
- Read the page param
- Fetch when page changes
- Render links for Next/Prev
1. Routes setup
// App.jsximport { BrowserRouter, Routes, Route } from 'react-router-dom';import PostsList from './PostsList';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/posts" element={<PostsList />} />
</Routes>
</BrowserRouter>
);
}
export default App;
2. Reading the page param
We’ll use the useSearchParams hook to get and set the page value.
// PostsList.jsximport { useSearchParams } from 'react-router-dom';
function PostsList() {
const [searchParams, setSearchParams] = useSearchParams();
// Read page from URL, default to 1
const page = parseInt(searchParams.get('page') || '1', 10);
// ...
}
3. Fetching data when page changes
Make sure your data-fetching effect depends on page, so it runs every time page updates.
import { useState, useEffect } from 'react';
function PostsList() {
// ...previous code...
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(`https://api.example.com/posts?page=${page}`)
.then(res => res.json())
.then(data => {
setPosts(data.items);
setLoading(false);
})
.catch(() => setLoading(false));
}, [page]); // ← include page here!
if (loading) return <p>Loading page {page}…</p>;
return (
<div>
<h2>Page {page}</h2>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
{/* Pagination links will go here */}
</div>
);
}
Also Read: How to Update ReactJS to the Latest Version Safely and Effectively
4. Next / Previous links
Use setSearchParams to change the page in the URL. This will re‑run the effect above.
function PostsList() { // ...state, useEffect, etc...
const goToPage = newPage => {
setSearchParams({ page: newPage });
};
return (
<div>
{/* ...posts list... */}
<div style={{ marginTop: 16 }}>
<button
onClick={() => goToPage(page - 1)}
disabled={page <= 1}
>
Previous
</button>
<button onClick={() => goToPage(page + 1)}>
Next
</button>
</div>
</div>
);
}
Key takeaways
- Always include your page value in the dependency array of useEffect.
- Use useSearchParams or useParams consistently, depending on whether you use query strings or path parameters.
- Changing the search params with setSearchParams triggers a re-render and re-fetch of data.