Reputation: 1576
I have a simple web page with login and search pages. I also have a navbar at the top to allow for switching between the two. The basic App.js
looks as follows:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
Now, the BaseRouter
and CustomLayout
are just
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
and
const CustomLayout = ({children}) => {
return(
<>
<Navbar/>
{children}
</>
);
}
export default CustomLayout;
Now, the navbar looks like this
import React from "react";
import {Menu} from 'antd';
import {Link} from "react-router-dom";
const Navbar = () => {
return (
<div>
<Menu mode="horizontal" theme={"dark"}>
<Menu.Item key="list">
<Link to={"/list"}>List</Link>
</Menu.Item>
<Menu.Item key={"login"}>
<Link to={"/login"}>Sign in</Link>
</Menu.Item>
</Menu>
</div>
);
}
export default Navbar
Let's keep components simple:
const Login = () => {
return (
<div>
login
</div>
);
}
export default Login
const List = () => {
return (
<div>
list
</div>
);
}
export default List
Now the problem is that when I click on links in the navbar, React doesn't re-render components even though the route changes. I've seen hundreds of answers on SO but I still can't figure it out.
NOTE
It is important for me to avoid refreshing or reloading the page.
EDIT
Strangely enough, when I change Router
to BrowserRotuer
it works fine, but I can't use my own history then.
Upvotes: 0
Views: 1390
Reputation: 1439
why don't you use BrowserRouter
from react-router-dom
package.
App.js
:- use BrowserRouter
from react-router-dom
import { BrowserRouter as Router, Switch } from 'react-router-dom'
function App() {
return (
<Router>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
BaseRouter.js
:- import Route
from react-router-dom
import { Route } from 'react-router-dom'
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Navbar.js
:-import React from "react";
import {Menu} from 'antd';
import {Link} from "react-router-dom";
const Navbar = () => {
return (
<div>
<Menu mode="horizontal" theme={"dark"}>
<Menu.Item key={"list"}>
<Link to="/list">List</Link>
</Menu.Item>
<Menu.Item key={"login"}>
<Link to="/login">Sign in</Link>
</Menu.Item>
</Menu>
</div>
);
}
export default Navbar
then if you want to use history
:-
import { useHistory } from 'react-router-dom'
const testFunctionComponent = () => {
const history = useHistory()
const handleClick = (urlPath) => {
// you can do
history.push(urlPath) // to go anywhere
}
return (
<>
<button onClick={() => handleClick('/anypath')}>Click Me!<button>
</>
)
}
Upvotes: 1
Reputation: 2972
Router
is low-level and expects you to manage things. BrowserRouter
already syncs with HTML5 history. If you want Router
, I think you have to manage the syncing yourself (e.g. <Link onClick={() => history.push(href)}>)
or listen to history for change detection. See Detect Route Change with react-router
Upvotes: 0
Reputation: 2932
I believe you cannot have the div inside the switch. You're not exposing the Route components to your switch statement.
Therefore, your url changes because your Navbar makes it change but your switch doesn't know what to do.
Try changing your base router to this:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<BaseRouter/>
</CustomLayout>
</Router>
);
}
export default App;
const BaseRouter = () => (
<Switch>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</Switch>
);
export default BaseRouter;
Upvotes: 0
Reputation: 1283
Change your BaseRouter
from this :
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
To this :
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Upvotes: 0