I have updated to react-router-dom
version 6 and the URL I see that it's updated but then the components are not rendered. Also when I refresh the page the component is still not rendering.
I have this code:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { createBrowserHistory } from 'history'
const history = createBrowserHistory()
function App() {
return (
<Router history={history}>
<Routes>
<Route path='/logout' element={<Logout/>} />
<Route path='/' element={<Authenticate/>}>
<Route index element={<Analysis />} />
<Route path='/analysis' element={<Analysis />} />
<Route path='/login' element={<Login/>} />
<Route path='/register' element={<Register/>} />
.....
</Route>
</Routes>
</Router>
)
}
const rootNode = document.getElementById('root')
ReactDOM.render(<App />, rootNode)
The only component that it does render is the <Authenticate/>
component. Inside this component when I am changing routes I have this code implemented
handleClick = e => {
console.log('e is :', e.key)
if (e.key !== '/logout') {
history.push(e.key)
}
}
Do I have something wrong on my implementation or something else?
I am using:
"react-router-dom": "^6.22.1",
"react": "^17.0.2",
"history": "^5.3.0",
The BrowserRouter
component doesn't consume any history
prop
declare function BrowserRouter( props: BrowserRouterProps ): React.ReactElement; interface BrowserRouterProps { basename?: string; children?: React.ReactNode; future?: FutureConfig; window?: Window; }
so the likely issue here is that your custom history
reference is effecting navigation actions outside the BrowserRouter
component's scope. In other words, the router is completely unaware of them and doesn't react to the external URL changes.
Because Authenticate
is a layout route component, it must render an Outlet
component for the nested routes to render out their element
content when the URL path is matched. Ensure this is the case.
BrowserRouter
(Preferred)Use the useNavigate
hook and navigate
function to effect navigation actions. Update Authenticate
and any other routed component to use the useNavigate
hook.
Example:
import { Outlet, useNavigate } from 'react-router-dom';
const Authenticate = () => {
const navigate = useNavigate();
handleClick = e => {
if (e.key !== '/logout') {
navigate(e.key); // <-- issue PUSH action
}
};
...
return (
...
<Outlet /> // <-- nested routes render content here
...
);
};
HistoryRouter
and custom history
objectImport and use the undocumented HistoryRouter
. Create and export your history
object separately so all components reference the same history reference.
Example:
history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;
import {
unstable_HistoryRouter as Router,
Routes,
Route
} from 'react-router-dom';
import history from './path/to/history';
function App() {
return (
<Router history={history}>
<Routes>
<Route path='/logout' element={<Logout/>} />
<Route path='/' element={<Authenticate/>}>
<Route index element={<Analysis />} />
<Route path='/analysis' element={<Analysis />} />
<Route path='/login' element={<Login/>} />
<Route path='/register' element={<Register/>} />
.....
</Route>
</Routes>
</Router>
)
}
Authenticate.jsx
import { Outlet } from 'react-router-dom';
import history from './path/to/history';
const Authenticate = () => {
...
handleClick = e => {
if (e.key !== '/logout') {
history.push(e.key); // <-- issue PUSH action
}
};
...
return (
...
<Outlet /> // <-- nested routes render content here
...
);
};
Only use this version if you really have a need for the external custom history
object, e.g. you are connecting your router to a Redux store or similar, otherwise, the first option is preferred.