I'm having a ton of difficulty finding the answer. Right now all my
<Route exact path='/' render={()=><Redirect to='/dashboard'/>}/>
does is change the url to ".../dashboard", but it doesn't refresh the page so that the component loads, only when I hit refresh does my component load.
How can I get <Redirect ... /> to refresh the page after redirect?
I have had success with window.location.reload(), but I don't know how to put it in. I've also tried adding <Redirect push to=.../> without luck.
setup a switch route and a Redirect component
<Switch>
<Redirect from='/' to='/dashboard'/>
<Route path='/dashboard' render={(props) => (
auth.isAuthenticated === true
? <Component {...props} />
: <Redirect to='/login' />
)}
/>
</Switch>
More on the docs
For react-router-dom v6. The below code is working for me,
import './App.css';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
import Dashboard from './Components/Dashboard';
function App() {
return (
<div className="App">
<Router>
<Routes>
<Route path="/" element={<Navigate to="/dashboard" />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Router>
</div>
);
}
export default App;
Related
I created a page using react-router-dom. On that I set a navbar and on that navbar I put two links (FormControl, Accordion). When the user will click that link the main body will change, nav bar should not change, it should remain constant on the page.
I tried to fix the issue and I am expecting that when a user clicks the links the navbar will not change.
import Accordion from "./component/Accordion";
import FormControl from "./component/FormControl";
import NavBar from "./component/NavBar";
import NoPage from "./component/NoPage";
import { Routes, Route } from 'react-router-dom';
function App() {
return (
<>
<Routes>
<Route path="/" element={<NavBar />} />
<Route path="/Accordion" element={<Accordion />} />
<Route path="/FormControl" element={<FormControl />} />
<Route path="/*" element={<NoPage />} />
</Routes>
</>
);
}
export default App;
app.js
index.js
main nav bar
when clicking on form control the nav bar get hidden
If you want the NavBar component to renders always, or at least consistently with a group of routes you should render it alone on its own route. With NavBar rendered on "/" when the user navigates to any other route the "/" will no longer be the matched route and the NavBar component will be unmounted.
Examples
Unconditionally rendered on its own.
import { Routes, Route } from 'react-router-dom';
function App() {
return (
<>
<NavBar />
<Routes>
<Route path="/" element={/* Need a home page component? */} />
<Route path="/accordion" element={<Accordion />} />
<Route path="/formcontrol" element={<FormControl />} />
<Route path="*" element={<NoPage />} />
</Routes>
</>
);
}
As part of a layout route that renders an Outlet component for nested routes.
import { Routes, Route, Outlet } from 'react-router-dom';
const AppLayout = () => (
<>
<NavBar />
<Outlet />
</>
);
function App() {
return (
<Routes>
<Route path="/" element={<AppLayout />}>
<Route index element={/* Need a home page component? */} />
<Route path="accordion" element={<Accordion />} />
<Route path="formcontrol" element={<FormControl />} />
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
);
}
I am a beginner with react-router-dom, there are two different states in the code when I dont use Navigate from react-router-dom , it works properly , but when I use the Navigate function it renders a blank page.
I have confirmed that all the individual components work and render properly.
Please help me solve this issue .
Here is my code of App.js without Navigate
import React from 'react';
import { Container } from '#material-ui/core';
import { BrowserRouter , Route , Routes , Navigate } from 'react-router-dom'
import PostDetails from './components/PostDetails/PostDetails';
import Home from './components/Home/Home';
import Navbar from './components/Navbar/Navbar';
import Auth from './components/Auth/Auth';
const App = () => {
const user = JSON.parse(localStorage.getItem('profile'));
return (
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route exact path="/" element ={<Home/>} />
<Route path="/auth" element={<Auth/>} />
<Route path="/posts" exact element={<Home/>} />
<Route path="/posts/search" exact element={<Home/>} />
<Route path="/posts/:id" exact element={<PostDetails/>} />
<Route path="/auth" exact element={() => (!user ? <Auth /> : <Navigate to="/posts" />)} />
</Routes>
</Container>
</BrowserRouter>
)
};
export default App;
Here is my code of App.js with Navigate which does not works
import React from 'react';
import { Container } from '#material-ui/core';
import { BrowserRouter , Route , Routes , Navigate } from 'react-router-dom'
import PostDetails from './components/PostDetails/PostDetails';
import Home from './components/Home/Home';
import Navbar from './components/Navbar/Navbar';
import Auth from './components/Auth/Auth';
const App = () => {
const user = JSON.parse(localStorage.getItem('profile'));
return (
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route path="/" exact component={() => <Navigate replace to="/posts" />} />
<Route path="/posts" exact element={<Home/>} />
<Route path="/posts/search" exact element={<Home/>} />
<Route path="/posts/:id" exact element={<PostDetails/>} />
<Route path="/auth" exact element={() => (!user ? <Auth /> : <Navigate replace to="/posts" />)} />
</Routes>
</Container>
</BrowserRouter>
)
};
export default App;
In react-router-dom#6 the Route components's element prop takes only a ReactNode, a.k.a. JSX. You've one route taking a component prop which is invalid, and two routes passing a function.
Use the element prop and pass JSX only.
Note that there is also no longer any exact prop, in RRDv6 all routes are always exactly matched.
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route path="/" element={<Navigate replace to="/posts" />} />
<Route path="/posts" element={<Home />} />
<Route path="/posts/search" element={<Home />} />
<Route path="/posts/:id" element={<PostDetails />} />
<Route
path="/auth"
element={!user ? <Auth /> : <Navigate replace to="/posts" />}
/>
</Routes>
</Container>
</BrowserRouter>
If you are trying to protect these "/posts*" routes then it is common to create a layout route to handle redirecting to the login route or render the protected routes.
Example:
const AuthLayout = ({ authenticated }) =>
authenticated
? <Outlet />
: <Navigate to="/auth" replace />;
...
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route element={<AuthLayout authenticated={!!user} />}>
<Route path="/posts" element={<Home />} />
<Route path="/posts/search" element={<Home />} />
<Route path="/posts/:id" element={<PostDetails />} />
</Route>
<Route path="/" element={<Navigate replace to="/posts" />} />
<Route
path="/auth"
element={!user ? <Auth /> : <Navigate replace to="/posts" />}
/>
</Routes>
</Container>
</BrowserRouter>
use element props instead component
<Route path="/" exact component={() => <Navigate replace to="/posts" />} />
<Route path="/" exact element={() => <Navigate replace to="/posts" />
Here is my App.js from my current project , I am facing an issue, whenever I render all my components individually which are mentioned in the commented part it gives me complete output, but as soon as I render it through the react-router-dom the page turns blank. Please help me with this.
import Topbar from "./components/topbar/Topbar";
import Homepage from "./pages/homepage/Homepage";
import Login from "./pages/login/Login";
import Register from "./pages/register/Register";
import Settings from "./pages/settings/Settings";
import Single from "./pages/single/Single";
import Write from "./pages/write/Write";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Header from "./components/header/Header";
import Posts from "./components/posts/Posts";
function App() {
const currentUser = true;
return (
// <>
// <Topbar/>
// <Header/>
// <Single/>
// <Homepage/>
// <Posts/>
// <Register/>
// <Login/>
// <Settings/>
// </>
<BrowserRouter>
<Topbar />
<Routes>
<Route exact path="/">
<Homepage />
</Route>
<Route path="/posts">
<Homepage />
</Route>
<Route path="/register">
{currentUser ? <Homepage /> : <Register />}
</Route>
<Route path="/login">{currentUser ? <Homepage /> : <Login />}</Route>
<Route path="/post/:id">
<Single />
</Route>
<Route path="/write">{currentUser ? <Write /> : <Login />}</Route>
<Route path="/settings">
{currentUser ? <Settings /> : <Login />}
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;
Try changing your routes to look something like this:
<Route exact path="/" element={<Homepage />} />
The component you want to render should be in the element prop.
https://reactrouter.com/docs/en/v6/getting-started/overview
https://reactrouter.com/docs/en/v6/upgrading/v5
<Route exact path="/" element={<Homepage />} />
The only time you can put something inside a Route as a child element is for nested routing. For example:
<Route path="/teams" element={<Teams />}>
<Route path=":teams" element={<Team />} />
</Route>
I have been through this. I think you should install React Router first (Already installed it seems)
npm install react-router-dom#6
I suggest using it in the following way -
function App() {
return (
<Router>
<div className='container'>
<div className='Header'>
<h2>Blog Site</h2>
</div>
<div className='links'> // Mention your links here
<ul>
<li>
<Link to="/tag">Tags</Link>
</li>
<li>
<Link to="/startup">Startups</Link>
</li>
</ul>
</div>
<Routes> // Describe your routes here
<Route exact path="/tag" element={<Tag />} />
<Route exact path="/startup" element={<Startup />} />
</Routes>
</div>
</Router>
);
}
I have picked small code piece from my project, you can try using my approach.
I have already tried various solutions, I am currently using it, unfortunately GA only tracks one path ('/')
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import '../sass/main.scss';
import {
HashRouter,
Route,
Switch,
} from 'react-router-dom';
const history = createHistory()
ReactGA.initialize('UA-XXXXXXX-1');
history.listen((location, action) => {
ReactGA.pageview(location.pathname + location.search);
console.log(location.pathname)
});
class Index extends Component {
render() {
return (
<>
<HashRouter history={history} >
<Route />
<ScrollUpButton ContainerClassName="AnyClassForContainer" />
<Header />
<Switch history={history}>
<Route exact path={"/"} component={() => <HomePage />}/>
<Route exact path={"/test"} component={() => <CategoryLinksNextPrev />}/>
<Route exact path={"/contact"} component={() => <Contact />}/>
<Route exact path={"/car/:category/"} component={CarCategory} />
<Route exact path={"/car/:category/:carname"} component={CarOnePageMain} />
<Route path="*" component={NotFound} />
</Switch>
<Footer />
</HashRouter>
</>
)
}
}
ReactDOM.render(<Index />, document.getElementById("index"));
In google analytics it only shows me one subpage, and exactly points to index.html
UPDATE
I found a very simple solution to this problem.
https://www.npmjs.com/package/react-router-ga
So that's my code now:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import '../sass/main.scss';
import {
HashRouter,
Route,
Switch,
} from 'react-router-dom';
import Analytics from 'react-router-ga';
class Index extends Component {
render() {
return (
<>
<HashRouter >
<Analytics id="UA-xxxxxxx-1" debug>
<ScrollUpButton ContainerClassName="AnyClassForContainer" />
<Header />
<Switch history={history}>
<Route exact path={"/"} component={() => <HomePage />}/>
<Route exact path={"/test"} component={() => <CategoryLinksNextPrev />}/>
<Route exact path={"/contact"} component={() => <Contact />}/>
<Route exact path={"/car/:category/"} component={CarCategory} />
<Route exact path={"/car/:category/:carname"} component={CarOnePageMain} />
<Route path="*" component={NotFound} />
</Switch>
<Footer />
</Analytics>
</HashRouter>
</>
)
}
}
ReactDOM.render(<Index />, document.getElementById("index"));
I had a similar issue recently.
It looks like Google Analytics loads on the page load. If you click on a link, GA will run again as the new page is loaded from scratch with a new URL.
You have to manually fire the GA page views when user moves around your single page application.
More info here - https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications
I want to hide the navbar in a login page.
I did it actually, but I can't see the navbar on other pages.
This code is part of My App.jsx file.
I make history in App's state. And I hide navbar, when this pathname is '/' or '/login'.
It works!
But then I typed the ID and password, and clicked the login button, got 'success' result, and navigated to '/main'.
Now I can't see navbar in main component too.
How can I do this?
Sorry about my short english. If you can't understand my question, you can comment.
constructor(props) {
super(props);
this.state = {
isAlertOpen: false,
history: createBrowserHistory(),
};
this.toggleAlert = this.toggleAlert.bind(this);
}
<BrowserRouter>
<div className="App">
{this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
: <Header toggleAlert={this.toggleAlert} />}
<div className="container">
{this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
: <Navbar />}
<Route exact path="/" render={() => <Redirect to="/login" />} />
<Route path="/login" component={Login} />
<Route path="/main" component={Main} />
<Route path="/user" component={User} />
<Route path="/hw-setting" component={Setting} />
<Route path="/hw-detail/:id" component={HwDetail} />
<Route path="/gas-detail/:id" component={GasDetail} />
{this.state.isAlertOpen ? <Alert /> : null}
</div>
</div>
</BrowserRouter>
login(event) {
event.preventDefault();
userService.login(this.state.id, this.state.password).subscribe(res => {
if (res.result === 'success') {
global.token = res.token;
this.props.history.push('/main');
} else {
alert(`[ERROR CODE : ${res.statusCode}] ${res.msg}`);
}
});
You could structure your Routes differently so that the Login component doesn't have the Header Like
<BrowserRouter>
<Switch>
<div className="App">
<Route exact path="/(login)" component={LoginContainer}/>
<Route component={DefaultContainer}/>
</div>
</Switch>
</BrowserRouter>
const LoginContainer = () => (
<div className="container">
<Route exact path="/" render={() => <Redirect to="/login" />} />
<Route path="/login" component={Login} />
</div>
)
const DefaultContainer = () => (
<div>
<Header toggleAlert={this.toggleAlert} />
<div className="container">
<Navbar />
<Route path="/main" component={Main} />
<Route path="/user" component={User} />
<Route path="/hw-setting" component={Setting} />
<Route path="/hw-detail/:id" component={HwDetail} />
<Route path="/gas-detail/:id" component={GasDetail} />
{this.state.isAlertOpen ? <Alert /> : null}
</div>
</div>
)
As of the latest release of React Router v6, it is no longer possible to pass a <div> component inside the Routes (v6) aka Switch(v5 or lower) to render a Navbar. You will need to do something like this:
Create two Layout components. One simply renders a Nav and the other one does not. Suppose we name them
<WithNav />
<WithoutNav />
You will need to import <Outlet /> from the React router and render inside the Layout components for the routes to be matched.
Then in your App or where ever you have your Router you will render like below ....
// WithNav.js (Stand-alone Functional Component)
import React from 'react';
import NavBar from 'your navbar location';
import { Outlet } from 'react-router';
export default () => {
return (
<>
<NavBar />
<Outlet />
</>
);
};
// WithoutNav.js (Stand-alone Functional Component)
import React from 'react';
import { Outlet } from 'react-router';
export default () => <Outlet />
// your router (Assuming this resides in your App.js)
<Routes>
<Route element={<WithoutNav />}>
<Route path="/login" element={<LoginPage />} />
</Route>
<Route element={<WithNav />}>
<Route path="/=example" element={<Example />} />
</Route>
</Routes>
LoginPage will not have a nav however, Example page will
Simplest way is use div tag and put components in which you want navbar and put login route component outside div tag:
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Login} />
<div>
<NavBar />
<Route exact path="/addproduct" component={Addproduct}></Route>
<Route exact path="/products" component={Products}></Route>
</div>
</Switch>
</Router>
</div>
Put the Route with path="/" below every other routes :
<Switch>
<Route path="/login" component={Login} />
<Route path="/" component={Home} />
</Switch>
It will work.
I'm was trying to solve this problem, what i did was add component helmet, to install it use : yarn add react-helmet --save.
import {Helmet} from 'react-helmet';
<Helmet>
<script src="https://kit.fontawesome.com/.....js" crossorigin="anonymous"></script>
</Helmet>
The accepted answer has problem if you need to add other default route within the switch if no other route matches, e.g., 404 page, not found page.
I ended up using simple css to hide navigation bar inside my login page.
class LoginPage extends React.Component<>{
...
// Hide navigation bar in login page. Do it inside ComponentDidMount as we need to wait for navbar to render before hiding it.
componentDidMount(){
document.getElementById('navigation-bar')!.style.display = "none";
}
componentWillUnmount(){
document.getElementById('navigation-bar')!.style.display = "flex";
}
render(){
return(
// your login/signup component here
...
)
}
}