I got headache trying to figure out why private route is not redirecting to the path I've setting up. I think a miss something but I don't know what.
Did someone help me figure out ?
here is my private route component :
import React, {useContext} from 'react';
import {Route, Redirect} from 'react-router-dom';
import AuthContext from '../../context/auth/Authcontext';
const PrivateRoute = ({component: Component, ...rest}) => {
const authContext = useContext(AuthContext);
const {isAuthenticated, loading} = authContext;
return (
<Route
{...rest}
render={props =>
!isAuthenticated && !loading ? (
<Redirect to='/pagelist' />
) : (
<Component {...props} />
)
}
/>
);
};
export default PrivateRoute;
I'm using context to handle all the authentification part.What I'm trying to do is if you are not logging you can't access the the dashboard.
here is my App.js :
import React, {Fragment, Component} from 'react';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import Navbar from './components/layouts/Navbar';
import Dashboard from './components/pages/Dashboard';
import Register from './components/auth/Register';
import Login from './components/auth/Login';
import PrivateRoute from './components/routing/PrivateRoute';
import AuthState from './context/auth/AuthState';
import AlertState from './context/alert/AlertState';
import setAuthToken from './utils/setAuthToken';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
return (
<AuthState>
<AlertState>
<Router>
<Fragment>
<Navbar />
<div className='container'>
<Alerts />
<Switch>
<PrivateRoute exact path='/' component={Dashboard} />
<Route exact path='/register' component={Register} />
<Route exact path='/login' component={Login} />
</Switch>
</div>
</Fragment>
</Router>
</AlertState>
</AuthState>
);
};
export default App;
I think I did everything correctly because when I'm watching in my console, current user are not authenticated but the dashboard is still accessible. Did I miss something ?
Related
I've created private route for check user logged in or not. But it is not redirecting to index page if user logged in.Here is my code.
Private route:
import React from 'react'
import { useSelector } from 'react-redux';
import { Redirect } from 'react-router-dom';
const Privateroute = ({children}) => {
const user = useSelector((state)=> state.user.value);
console.log("Privateroute");
console.log(user.email);
return user.email == null ? children : <Redirect to="/auth/login" />
};
export default Privateroute;
My App.js looks like this
import React from "react";
import ReactDOM from "react-dom";
import { HashRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import AdminLayout from "layouts/Admin.js";
import AuthLayout from "layouts/Auth.js";
import { store } from "./views/examples/redux/store";
import { Provider, useDispatch , useSelector } from 'react-redux'
import Privateroute from "views/examples/Privateroute";
import {login} from './views/examples/redux/cred'
function App() {
return (
<Router>
<Switch>
<Route path="/admin" render={(props) => <AdminLayout {...props} />} />
<Route path="/auth" render={(props) => <AuthLayout {...props} />} />
<Privateroute> <Redirect from="/" to="/admin/index" /> </Privateroute>
</Switch>
</Router>
)
}
export default App
What I am doing wrong here?
You dont need to write a Redirect into Private component
ref this link :https://ui.dev/react-router-v5-protected-routes-authentication
App.js
import React from "react";
import ReactDOM from "react-dom";
import { HashRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import AdminLayout from "layouts/Admin.js";
import AuthLayout from "layouts/Auth.js";
import { store } from "./views/examples/redux/store";
import { Provider, useDispatch , useSelector } from 'react-redux'
import Privateroute from "views/examples/Privateroute";
import {login} from './views/examples/redux/cred'
function App() {
return (
<Router>
<Switch>
<Route path="/admin" render={(props) => <AdminLayout {...props} />} />
<Route path="/auth" render={(props) => <AuthLayout {...props} />} />
<Privateroute>
//your private components only here like profile etc...
</Privateroute>
</Switch>
</Router>
)
}
export default App
I'm new to react and is trying out the React.lazy and Suspense imports, and I just have to say, I love them!!! My website went from 45% in performance up to 50-60% and that is without optimizing images! Google search results, here I come!
However, I have a problem, I don't know how to lazy load a component which is rendered in my custom ProtectedRoute and react-router-dom v5.
The lazy loading works and takes effect when I use the React-router-doms native Route, but when I want to load a protected component via one in my custom protected routes, nothing happens, no error message in console or on the website, just a white screen. I suspect there's some problem with the import and code being put in the wrong place.
APP
import React, { Suspense } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import ProtectedRoute from "./pages/middleware/ProtectedRoute";
const Login = React.lazy(() => import("./pages/Login"));
const WebsiteCRUDs = React.lazy(() => import("./pages/WebsiteCRUDs"));
function App() {
return (
<div className="App">
<Router>
<Switch>
{/* This one works */}
<Suspense fallback={<div>Loading</div>}>
<Route exact path="/admin" component={Login} />
</Suspense>
{/* This one does NOT work */}
<Suspense fallback={<div>Loading</div>}>
<ProtectedRoute exact path="/admin/crud" component={WebsiteCRUDs} />
</Suspense>
</Switch>
</Router>
</div>
);
}
export default App;
ProtectedRoute:
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { useEffect, useState } from "react";
const ProtectedRoute = ({ component: Component, ...rest }) => {
const [isAuth, setIsAuth] = useState(false);
const [isLoading, setIsLoading] = useState(true);
// Logic validation goes here with redirect if user is not auth.
return (
<Route
{...rest}
render={(props) =>
isLoading ? (
<h1>Checking Validation</h1>
) : isAuth ? (
<Component {...props} />
) : (
<Redirect
to={{ pathname: "/admin", state: { from: props.location } }}
/>
)
}
/>
);
};
export default ProtectedRoute;
Please try like this
import React, { Suspense } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import ProtectedRoute from "./pages/middleware/ProtectedRoute";
const Login = React.lazy(() => import("./pages/Login"));
const WebsiteCRUDs = React.lazy(() => import("./pages/WebsiteCRUDs"));
function App() {
return (
<div className="App">
<Router>
<Switch>
<Suspense fallback={<div>Loading</div>}>
<Route exact path="/admin" component={Login} />
<ProtectedRoute exact path="/admin/crud" component={WebsiteCRUDs} />
</Suspense>
</Switch>
</Router>
</div>
);
}
export default App;
I want to redirect the unauthenticated user to /login. I have a property in my context called loggedIn, when it is false I want to make a redirect to HomePage i.e "/".
I just got confused due to the route structure. I'm seeing something like a protected route everywhere.
import React, { useContext, useEffect } from "react";
import { Redirect, Route } from "react-router-dom";
import { IonApp, IonRouterOutlet, IonSplitPane } from "#ionic/react";
import { IonReactRouter } from "#ionic/react-router";
import { setupConfig } from "#ionic/react";
import { Plugins, Capacitor } from "#capacitor/core";
import { useHistory } from "react-router-dom";
import Home from "./pages/Home/Home";
/* Core CSS required for Ionic components to work properly */
import "#ionic/react/css/core.css";
/* Basic CSS for apps built with Ionic */
import "#ionic/react/css/normalize.css";
import "#ionic/react/css/structure.css";
import "#ionic/react/css/typography.css";
/* Optional CSS utils that can be commented out */
import "#ionic/react/css/padding.css";
import "#ionic/react/css/float-elements.css";
import "#ionic/react/css/text-alignment.css";
import "#ionic/react/css/text-transformation.css";
import "#ionic/react/css/flex-utils.css";
import "#ionic/react/css/display.css";
import "../src/utils/spacing.css";
/* Theme variables */
import "./theme/variables.css";
/* Components */
import Dashboard from "./pages/Dashboard/Dashboard";
import SideMenu from "./components/SideMenu/SideMenu";
import LoginPage from "./pages/Login/Login";
import SignupPage from "./pages/Signup/Signup";
import Create from "./pages/Create/Create";
import Edit from "./pages/Edit/Edit";
import { AuthContext, AuthProvider } from "./providers/context/AuthContext";
const App: React.FC = () => {
const history = useHistory();
return (
<IonApp>
<AuthProvider>
<IonReactRouter>
<IonSplitPane contentId="main">
<SideMenu />
<IonRouterOutlet id="main">
<Route path="/dashboard/:name" component={Dashboard} exact />
<Route path="/dashboard/Edit/:id" component={Edit} exact />
// if !user navigate to login component
<Route path="/create" component={Create} exact />
<Route path="/signup" component={SignupPage} exact />
<Route path="/" component={Home} exact />
<Redirect from="/dashboard" to="/dashboard/Home" exact />
</IonRouterOutlet>
</IonSplitPane>
</IonReactRouter>
</AuthProvider>
</IonApp>
);
};
export default App;
Might be useful for anyone: is solved it by using the Private Route and pubic Route trick
I Created a component called PrivateRoute.tsx and added the following:
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import { EnrolleeContext } from "../providers/context/EnrolleeContext";
const PrivateRoute = ({ component: Component, ...rest }: any) => {
const { loggedIn } = useContext(EnrolleeContext);
return (
// Show the component only when the user is logged in
// Otherwise, redirect the user to /signin page
<Route
{...rest}
render={(props) =>
loggedIn ? <Component {...props} /> : <Redirect to="/" />
}
/>
);
};
export default PrivateRoute;
Also created a Public Route, added restricted to be able to restrict Components if restricted == true, meaning the Route is Private, if false, otherwise.
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import { EnrolleeContext } from "../providers/context/EnrolleeContext";
const PublicRoute = ({ component: Component, restricted, ...rest }: any) => {
const { loggedIn } = useContext(EnrolleeContext);
return (
// restricted = false meaning public route
// restricted = true meaning restricted route
<Route
{...rest}
render={(props) =>
loggedIn && restricted ? (
<Redirect to="/dashboard/Home" />
) : (
<Component {...props} />
)
}
/>
);
};
export default PublicRoute;
Updated App.tsx
<PublicRoute restricted={false} component={Home} path="/" exact />
<PublicRoute
restricted={true}
component={LoginPage}
path="/login"
exact
/>
<PrivateRoute
component={Dashboard}
path="/dashboard/:name"
exact
/>
<PrivateRoute component={Create} path="/create" exact />
<PublicRoute
restricted={false}
component={ForgotPassword}
path="/forgot-password"
exact
/>
Other Routes like forgot password is open to the public`, while Create is Private, so it is at your own discretion.
After adding PublicRoute and PrivateRoute my app not working popup login and signup. It displaying a blank screen. Before adding PublicRoute and PrivateRoute, my app working fine with Route.
The App has an initial home page when I click on the Merchant button it should popup for the login page. Please find the below screenshot.
But it displays with a blank screen. Please find below screenshot
Please help me to fix this issue.
AppRouter.js
import React from 'react';
import {Router, Route , Switch} from 'react-router-dom';
import createHistory from 'history/createBrowserHistory';
import { HomePage } from '../components/HomePage';
import DashboardPage from '../components/DashboardPage';
import StartLogin from '../components/StartLogin';
import { UserForm } from '../components/UserForm';
import PublicRoute from './PublicRouter';
import PrivateRoute from './PrivateRouter';
export const history = createHistory()
const AppRouter = () => (
<Router history={history}>
<div>
<Switch>
<PublicRoute path="/" component={HomePage} exact={true}/>
<PrivateRoute path="/dashboard" component={DashboardPage} />
</Switch>
</div>
</Router>
);
export default AppRouter;
PublicRoute.js
import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
export const PublicRoute = ( {
isAuthenticated,
component: Component,
...rest}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<div>
<Redirect to='/dashboard' />
</div>
) : (
<Component {...props} />
)
)}/>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.merchLogin
})
export default connect(mapStateToProps)(PublicRoute);
PrivateRoute.js
import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
import { HomePage } from '../components/HomePage';
export const PrivateRoute = ( {
isAuthenticated,
component: Component,
...rest}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<div>
<HomePage />
<Component {...props} />
</div>
) : (
<Redirect to='/' />
)
)}/>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.merchLogin
})
export default connect(mapStateToProps)(PrivateRoute);
Remove isAuthenticated from PublicRoute.js
<Route path="/" component={HomePage} exact={true}/>
I am learning redux with react and hit a mental roadblock, I have the following entry index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Redirect, Route} from 'react-router-dom';
import {Provider} from 'react-redux';
import store from './store';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';
import Main from './components/front/Main';
import Login from './components/front/Login';
import Home from './components/front/Home';
import Register from './components/front/Register';
import Forgot from './components/front/Forgot';
import Verify from './components/front/Verify';
import Dashboard from './components/back/Dashboard';
import './css/app.css';
import Auth from './components/Auth';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
Auth.isLogged ? ( //<-need to get props here
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/',
state: { from: props.location }
}}/>
)
)}/>
)
const App = () => (<BrowserRouter>
<div>
{/* PUBLIC */}
<Route path={'/'} exact component={Home}/>
<Route path={'/login'} component={Login}/>
<Route path={'/register'} component={Register}/>
<Route path={'/forgot'} component={Forgot}/>
<Route path={'/verify'} component={Verify}/>
{/* PRIVATE */}
<PrivateRoute path="/dashboard" component={Dashboard}/>
</div>
</BrowserRouter>);
ReactDOM.render(<Provider store={store}><App/></Provider>, document.getElementById('root'));
Overall redux works, the only problem is in this file, as I am not exporting anything, I can't get connect to work.
Ideally Auth.isLogged should be either true or false based on isAuthenticated prop, but I can't get the value passed in any way to the entry index.js
import React from 'react';
import { connect } from 'react-redux';
#connect((store) => {
return {isAuthenticated: store.auth.isAuthenticated, authenticating: store.auth.authenticating};
})
export default class Auth extends React.Component {
//Can't get anything from here to index.js
}
Please any help would be greatly appreciated!
If I understand correctly, you’re trying to provide context of store.auth.isAuthenticated to PrivateRoute.
If you declare App in its' own file you can connect it to the store and then pass the value of isAutenticated to your PrivateRoute component
//App.js
import React, { Component } from 'react'
import { withRouter, Switch, Route } from 'react-router-dom'
import { connect } from 'react-redux'
import PrivateRoute from 'components/PrivateRoute'
#withRouter
#connect(store => ({
isAuthenticated: store.auth.isAuthenticated,
authenticating: store.auth.authenticating
}))
class App extends Component {
render() {
const { isAuthenticated } = this.props
return (
<span>
{/* PUBLIC */}
{ !isAuthenticated &&
<Switch>
<Route path={'/'} exact component={Home}/>
<Route path={'/login'} component={Login}/>
<Route path={'/register'} component={Register}/>
<Route path={'/forgot'} component={Forgot}/>
<Route path={'/verify'} component={Verify}/>
</Switch>
}
{/* PRIVATE */}
{ isAuthenticated &&
<PrivateRoute
isAuthenticated={isAuthenticated}
path="/dashboard"
component={Dashboard}
/>
}
</span>
)
}
}
export default App
For readability sake you could make this change in index.js
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root')
)
You may or may not need to wrap connect(App) inside of withRouter, but the way I was handling my routing made this part necessary.