I was trying to implement deep links(not sure if this is the correct term) in my react project
what I want to do is this :
the admin gets a mail: "this user can't login: http://localhost:3000/admin/customer-profile/b1d4a11f-4f6c-4dc1-98a9-ac0c30486c16"
the admin is not logged in
the admin clicks the link and is forwarded to the login page
the admin enters his login details
(the new part)
he is forwarded to /admin/customer-profile/b1d4a11f-4f6c-4dc1-98a9-ac0c30486c16
so in the fifth point the admin is redirected to the page link was for instead of going to the homepage.
Below are some snippets to give more info regarding this:
<div className="App">
{ready && <Router basename="/admin">
<Switch>
<Route path="/login">
<Login />
</Route>
<Route path="/privacypolicy">
<PrivacyPolicy />
</Route>
<Route path="/loginhelp">
<Help />
</Route>
<Route path="/termsconditions">
<TermsConditions />
</Route>
<PrivateRoute path="/logout">
<Logout />
</PrivateRoute>
<Route path="/">
<SideBar />
<Switch>
<PrivateRoute path="/tier-list">
<TierList />
</PrivateRoute>
<PrivateRoute path="/privacy-policy">
<PrivacyPolicy />
</PrivateRoute>
<PrivateRoute path="/help">
<Help />
</PrivateRoute>
</Switch>
</Route>
</Switch>
</Router>}
</div>
Below is how PrivateRoute looks like :
function PrivateRoute({ children, ...rest }: any) {
return (
<Route
{...rest}
render={({ location }) =>
userInfo != null ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
)
}
Any ideas How I shall modify this part to achieve the functionality?
Okay so I solved the problem. What I did was that I passed a pathName prop to the Login component and then if the user was logged in I redirect him to that page but if not then rendered the login page.
Related
These are my public routes
export const PublicRoutes = () => {
return (
<Switch>
<Route path="/" exact component={Login} />
<Route path={constant.component.logout.url} exact={true} component={Logout} />
<Route path={constant.component.register.url} exact= {true} component={SignUp} />
<Route path={constant.component.forgotPassword.url} exact={true} component={ForgotPassword} />
</Switch>
)
}
This is my index.js
ReactDOM.render(
<React.StrictMode>
<AlertProvider template={AlertTemplate} {...options}>
<Router>
<App />
</Router>
</AlertProvider>
</React.StrictMode>,
document.getElementById('root')
);
This is my app.js where I am trying to render routes based on accessToken in the local storage
return (
<>
{token ? <DashboardLayout /> : <PublicRoutes />}
</>
)
And finally this my dashboard layout where I want the authenticated routes to be shown to the right of the sidebar
<>
<SideBar>
<div className="w-100">
<Switch>
<Route path="/dashboard" component={Dashboard} />
<Route path="/my-account" component={Account} />
</Switch>
</div>
<Footer>
</>
Now, when I login, it redirects me to "/dashboard" the url changes but the page shows an empty screen and it works if I refresh the page manually. What am I doing wrong? Thanks
Are you sure your token is not empty right after you login ? Maybe your token is empty at this moment, PublicRoutes is rendered and that's why the /dashboard route display an empty screen. Maybe your token only gets value after refresh.
I am new on reactjs and stuck in a scenario like when I login the application using credentials and lands on the dashboard page, after when I navigate to some other page like List page from dashboard and try to refresh the page on list page it take me back to dashboard page instead to stay on the current page i.e List page.
Below is the Route Page of my code.
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/forgotPassword" component={ForgotPassword} />
<Route exact path="/changePassword" component={ChangePassword} />
<PrivateRoutes exact path="/" component={Dashboard} />
<PrivateRoutes exact path="/list" component={List} />
<PrivateRoutes exact path="/listDetails/:id" component={ListDetails} />
</Switch>
</BrowserRouter>
And Private route code is
class PrivateRoute extends Component {
render() {
let componentData = '';
componentData = <div><SideNavigation /> <Route render={() => <this.props.component {...this.props} />} /> </div>;
return componentData;
}
}
I am using reactjs.
I have multiple following routes in my index.js file
<BrowserRouter>
<App>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/Login" component={SignIn} />
<Route exact path="/Sign-up" component={SignUp} />
<Route exact path="/Orders" component={Orders} />
<Route exact path="/Category" component={Category} />
<Route exact path="/Shops" component={Shops} />
</Switch>
</App>
</BrowserRouter>
initially when user goes to base URL suppose
Http://localhost:3000
he should be redirected to
Http://localhost:3000/Shops page if value of localstorage item is null
and also if user tries to visit other pages he should be redirected to the /Shops page.
One way of doing this is using HOC but further i'll be adding auth soo there i'll have to wrap the component in route with HOC like this
<Route exact path="/Orders" component={AuthGuard(Orders)} />
I dont know whether I can do like this
<Route exact path="/Orders" component={AuthGuard, ShopGuard(Orders)} />
soo how can i achieve this without using HOC or how can I wrap 2 HOC for a single component.
Thanks.
function HandleRedirection() {
const RedirectToShop = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={(props) =>
localStorage.getItem('user') ? (
<App>
<Component {...props} />
</App>
) : (
<Redirect to="/shop" />
)}
/>
);
};
return (
<BrowserRouter basename={`/`}>
<Switch>
<Route path={`/shop`} component={Shops} />
<RedirectToShop exact path={`/login`} component={Signin} />
<RedirectToShop exact path={`/order`} component={Order} />
<RedirectToShop exact path={`/category`} component={Category} />
<Redirect to="/shop" />
</Switch>
</BrowserRouter>
);
}
Create a custom Route component that can check localStorage and redirect to "/shop" if condition is (or isn't?) met.
const ShopGuardRoute = ({ component: Component, ...props }) => (
<Route
{...props}
render={routeProps => {
const item = localStorage.getItem("key");
// Do all your conditional tests here
return item !== null ? (
<Component {...routeProps} />
) : (
<Redirect to="/shop" />
);
}}
/>
);
Usage
<BrowserRouter>
<App>
<Switch>
<ShopGuardRoute path="/Login" component={SignIn} />
<ShopGuardRoute path="/Sign-up" component={SignUp} />
<ShopGuardRoute path="/Orders" component={Orders} />
<ShopGuardRoute path="/Category" component={Category} />
<Route path="/Shops" component={Shops} />
<Route path="/" component={Home} />
</Switch>
</App>
</BrowserRouter>
If you plan on adding an authentication check then auth-workflow may help.
I think you can just do something like this on all the required pages if(condition // your local storage null check) { history.push(/yourPath, dataIfAny); }
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
...
)
}
}
I have a repo to reproduce this and see the error: https://github.com/rublev/parcel-static1/tree/master
The basic structure of my routes is as follows:
// app/app.js
const render = Component => {
ReactDOM.render(
<AppContainer>
<Provider store={ store }>
<ConnectedRouter history={ history }>
<Route component={ Component } />
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('react-root')
)
}
// app/containers/App/index.js
<div className='app'>
<Switch location={ location }>
<Route exact path='/' render={() => (
loggedIn ? (
<Redirect to='/organizations' push />
) : (
<Redirect to='/onboarding' push />
)
)}/>
<Route path='/organizations' component={ Organizations } />
<Route path='/onboarding' component={ Onboarding } />
<Route path='/settings' component={ Settings } />
</Switch>
</div>
// app/flows/onboarding/Onboarding/index.js
<div>
<Route exact path={`${match.url}`} component={ Start }/>
<Route path={`${match.url}/signup`} component={ SignUp }/>
<Route path={`${match.url}/name`} component={ Name }/>
<Route path={`${match.url}/structure`} component={ Structure }/>
<Route path={`${match.url}/pricing`} component={ Pricing }/>
<Route path={`${match.url}/continue`} component={ Continue }/>
</div>
// app/flows/onboarding/Start/index.js
<div className='start'>
Start Page
</div>
I'm not sure where the error could be coming from or how to do this different.
I have three main routes:
/onboarding
/organizations
/settings
I'd like to redirect to either /onboarding or /settings depending on login state. Once at either of these main routes, there will be sub routes.
What is the proper way to set these routes up with a redirect without causing a redirect error?
error on launching localhost:8080/:
In your render function, change
<Route component={ Component } />
to
<Component />
Also, you shouldn't need to pass location as a prop into the Switch in App.