I'm trying to implement pagination on a route with react-router and react-router-bootstrap. The issue is that I'm using LinkContainers that should render the same route with a different search parameter that contains the 'page' I'm jumping to, but when i click it, it just updates the address bar in the browser bud doesn't re-render the route.
The setup:
{"dependencies": {
"axios": "^0.26.0",
"bootstrap": "^5.1.3",
"react": "^17.0.2",
"react-bootstrap": "^2.2.0",
"react-dom": "^17.0.2",
"react-router-bootstrap": "^0.26.0",
"react-router-dom": "^6.2.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
}}
App.js:
import { Container } from 'react-bootstrap'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import CompanyCreateScreen from './screens/CompanyCreateScreen'
import CompanyDirScreen from './screens/CompanyDirScreen'
function App() {
return (
<Router>
<main className="py-3">
<Container className="cont-width">
<Routes>
<Route path="/" exact element={<CompanyDirScreen />} />
<Route path="/new_company" element={<CompanyCreateScreen />} />
</Routes>
</Container>
</main>
</Router>
)
}
CompanyDirScreen.jsx :
(most of it)
import React, { useEffect, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { LinkContainer } from 'react-router-bootstrap'
import { Row, Col, Button } from 'react-bootstrap'
import UniContainer from '../components/UniContainer'
import Loader from '../components/Loader'
import Message from '../components/Message'
import CompanyList from '../components/CompanyList'
import Paginate from '../components/Paginate'
import axios from 'axios'
const API_URL = 'http://localhost:8000/api'
const CompanyDirScreen = () => {
const [companies, setCompanies] = useState({})
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [page, setPage] = useState(0)
const [pages, setPages] = useState(0)
// Location info to determine the page to jump to
const location = useLocation()
let keywords = location.search
useEffect(() => {
console.log(keywords)
getCompanies((keywords = keywords))
}, [])
// Get companies
const getCompanies = async (keywords = '') => {
setLoading(true)
try {
const { data } = await axios.get(`${API_URL}/companies/${keywords}`)
setCompanies(data.companies)
setPage(data.page)
setPages(data.pages)
} catch (error) {
const e =
error.response && error.response.data.detail
? error.response.data.detail
: error.message
setError(e)
}
setLoading(false)
}
// Delete single company
const deleteCompany = async (id) => {
}
return (
<UniContainer>
<Row className="mb-3">
<Col>
<h3>Directorio de empresas</h3>
</Col>
<Col xs={3}>
<LinkContainer to="/new_company">
<Button>Nueva empresa</Button>
</LinkContainer>
</Col>
</Row>
{loading ? (
<Loader />
) : error ? (
<Message variant="danger">{error}</Message>
) : companies.length === 0 ? (
<Message variant="secondary">
Aun no hay empresas registradas, se el primero haciendo click en{' '}
<b>"Añadir empresa"</b>
</Message>
) : (
<>
<CompanyList companies={companies} handleDelete={deleteCompany} />
<Paginate page={page} pages={pages} />
</>
)}
</UniContainer>
)
}
export default CompanyDirScreen
... pagination is a separate component
Paginate.jsx
import { Pagination } from 'react-bootstrap'
import { LinkContainer } from 'react-router-bootstrap'
const Paginate = ({ pages, page }) => {
return (
pages > 1 && (
<Pagination className="justify-content-center">
{page > 1 && (
<LinkContainer to={`/?page=${page - 1}`}>
<Pagination.Prev />
</LinkContainer>
)}
{[...Array(pages).keys()].map((x) => (
<LinkContainer key={x + 1} to={`/?page=${x + 1}`}>
<Pagination.Item active={x + 1 === page}>{x + 1}</Pagination.Item>
</LinkContainer>
))}
{page !== pages && (
<LinkContainer to={`/?page=${page + 1}`}>
<Pagination.Next />
</LinkContainer>
)}
</Pagination>
)
)
}
export default Paginate
Right now when clicking any of the 'pagination' links it updates the address bar in the browser like this:
http://localhost:3000/ -> http://localhost:3000/?page=2 -> http://localhost:3000/?page= etc...
But it doesn't update the page contents and the console doesn't show any errors/warnings.
I can, however, select the url (eg http://localhost:3000/?page=2) and hit enter manually in the browser address bar and then it renders the desired page.
I'm suspecting it has something to do with the links being in a separate component, I think it's possible to create a function in CompanyDirScreen.jsx that 'navigates' to the requested page and pass it as a prop to Paginate.jsx although it feels a little messy, other option is to do the pagination directly in CompanyDirScreen.jsx but then I wouldn't be able to reuse the component in other routes I'm planning to.
Is there a way to use LinkContainer to navigate between pages as described?