Reputation: 389
Despite checking all the answers already posted on stack overflow I coudn't find the solution for my case, so I'll post it.
I'm using {Router} from 'react-router (v6) to be able to use a custom history object to be able to navigate in my redux actions.
Here are my files:
index.tsx
import { Router } from 'react-router';
import myHistory from './utils/history';
ReactDOM.render(
<Provider store={store}>
<Router navigator={myHistory} location={myHistory.location}>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
App.tsx
import MainNavigation from './components/navigations/MainNavigation';
import Routes from './routes/Routes';
const App = () => {
return (
<>
<MainNavigation />
<Routes />
</>
);
};
export default App;
MainNavigation.tsx
import { Link } from 'react-router-dom';
const MainNavigation = () => {
return (
<nav className='navigation'>
<ul>
<li>
<Link to='/'>Home</Link>
</li>
<li>
<Link to='/contact'>Contact</Link>
</li>
<li>
<Link to='/about'>A propos</Link>
</li>
<li>
<Link to='/user-profile'>Votre compte</Link>
</li>
</ul>
</nav>
);
};
export default MainNavigation;
Route.ts
import { Route, Routes as Routing } from 'react-router';
const Routes = () => {
return (
<Routing>
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/contact' element={<ContactForm />} />
<Route path='/user-profile' element={<UserAccount />} />
{/* <Route path='*' component={Error404} /> */}
{/* <Navigate to='/' /> */}
</Routing>
);
};
export default Routes;
The issue: when I click on one of the link the url changes to the corresponding path but the component doesn't render. I have to refresh the page to actually make it appear. I really don't know what's going on.
Thank you.
Upvotes: 6
Views: 8898
Reputation: 202605
From what I can tell you've not correctly implemented your Router
component.
If you examine one of the higher-level routers, like BrowserRouter
you'll notice they internalize the history
object and also store the current location from the result of a navigating action (history.listen
).
export function BrowserRouter({ basename, children, window }: BrowserRouterProps) { let historyRef = React.useRef<BrowserHistory>(); if (historyRef.current == null) { historyRef.current = createBrowserHistory({ window }); } let history = historyRef.current; let [state, setState] = React.useState({ action: history.action, location: history.location }); React.useLayoutEffect(() => history.listen(setState), [history]); return ( <Router basename={basename} children={children} location={state.location} navigationType={state.action} navigator={history} /> ); }
Create a CustomRouter
that consumes a custom history
object and manages the state:
const CustomRouter = ({ history, ...props }) => {
const [state, setState] = useState({
action: history.action,
location: history.location
});
useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
{...props}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
};
Import and use your new custom router instead.
import { CustomRouter } from './components/router';
import myHistory from './utils/history';
ReactDOM.render(
<Provider store={store}>
<Router history={myHistory}>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
Upvotes: 4
Reputation: 897
you need to include 'index' if you wish to use the '/' route.
<Route path='/about' index element={<About />} />
Also, React Router v6 is radically different to v5. it switches to the new Outlet based routing. In order to display your pages, you need to have an Outlet in your registered Route component. For example, in the app.js component, you need to add <Outlet />
in order to render these pages.
I like to think of the new routing as Container-based navigation. So create a component called AboutContainer. Include <Outlet />
in this component.
export const AboutContainer = () => (
<Outlet />
)
Then, add a component called AboutPage and put your about page logic inside. In your Routes, nest this About page as a new route inside your AboutContainer Router logic;
<Routes>
<Route path='/about' element={<AboutContainer />}>
<Route path='/' index element={<AboutPage />} />
</Route>
...
</Routes>
This means that every time you navigate to /about, you are shown the AboutPage component. Take it a step further and add an additional route
<Routes>
<Route path='/about' element={<AboutContainer />}>
<Route path='/' index element={<AboutPage />} />
<Route path='/you' index element={<AboutYouPage />} />
</Route>
...
</Routes>
This is how routing is now handled in React Router 6
Upvotes: 1
Reputation: 892
You can use your routes inherited way like;
<Routes>
<Route path="/">
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<ContactForm />} />
<Route path="user-profile" element={<UserAccount />} />
<Route path="*" element={<NoMatch />} />
</Route>
</Routes>
Upvotes: 1