I have an APP using React and Redux, and I wanted to load a NotFound component when the user enters an invalid route. I found online a way to solve that problem, that is by putting all the routes inside a switch, including the NotFound component.
The problem is that, in my app, I can't put all my routes inside a Switch because There is a single component that needs to be stretched to the entire page, while all the other components need to be inside a "container". The way I have it below (see the code), the NotFound component works for all cases, except when I'm on the "landing" component route (where the NotFound component always displays).
I tried to put the landing component inside the Switch with the "container" div but the app crashes.
Is there any way to solve this? (keeping the landing component out of the container, and the other components inside)
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Route exact path="/" component={Landing} />
<div className="container">
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:handle" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
<PrivateRoute
exact
path="/add-experience"
component={AddExperience}
/>
<PrivateRoute
exact
path="/add-education"
component={AddEducation}
/>
<PrivateRoute
exact
path="/edit-education/:id"
component={EditEducation}
/>
<PrivateRoute exact path="/feed" component={Posts} />
<PrivateRoute exact path="/post/:id" component={Post} />
<Route component={NotFound}/>
</Switch>
</div>
<Footer />
</div>
</Router>
</Provider>
);
}
}
You can make a separate router for all other components except landing page.
// App.js
import NonLandingPages from './NonLandingPages';
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Switch>
<Route exact path="/" component={Landing} />
<Route component={NonLandingPages}/>
</Switch>
<Footer />
</div>
</Router>
</Provider>
);
}
}
Separate router for all other pages
// NonLandingPages.js
class NonLandingPages extends Component {
render() {
return (
<div className="container">
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:handle" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
<PrivateRoute
exact
path="/add-experience"
component={AddExperience}
/>
<PrivateRoute
exact
path="/add-education"
component={AddEducation}
/>
<PrivateRoute
exact
path="/edit-education/:id"
component={EditEducation}
/>
<PrivateRoute exact path="/feed" component={Posts} />
<PrivateRoute exact path="/post/:id" component={Post} />
<Route component={NotFound}/>
</Switch>
</div>
);
}
}
Related
My problem is ı have a routes like that but when i try for example http://localhost:3000/examp1
I just want to redirect to HomePage how can i do that when i write something http://localhost:3000/*** ı go the page but nothing shows how can i detect and how can i redirect the homepage ? anyone help ?
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd' component={fas} exact />
<Route path='/asd' component={fasd} exact />
</Switch>
</Router>
Adding a <Route /> at the bottom without a path attribute inside the <Switch> tag should work for when there's no match, and then use a <Redirect /> tag to redirect to the homepage.
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd' component={fas} exact />
<Route path='/asd' component={fasd} exact />
<Route component={() => <Redirect to="/" />} />
</Switch>
</Router>
How to properly render a 404 page in React with React-Router?
https://reactrouter.com/web/api/Redirect
You can simply use Redirect component of react-router-dom library.
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} />
<Redirect to="/" />
</Switch>
</Router>
DefaultRoute and NotFoundRoute were removed in react-router 1.0.0.
I'd like to emphasize that the default route with the asterisk has to be last in the current hierarchy level to work. Otherwise it will override all other routes that appear after it in the tree because it's first and matches every path.
For react-router 1, 2 and 3
If you want to display a 404 and keep the path (Same functionality as NotFoundRoute)
<Route path='*' exact={true} component={My404Component} />
If you want to display a 404 page but change the url (Same functionality as DefaultRoute)
<Route path='/404' component={My404Component} />
<Redirect from='*' to='/404' />
Example with multiple levels:
<Route path='/' component={Layout} />
<IndexRoute component={MyComponent} />
<Route path='/users' component={MyComponent}>
<Route path='user/:id' component={MyComponent} />
<Route path='*' component={UsersNotFound} />
</Route>
<Route path='/settings' component={MyComponent} />
<Route path='*' exact={true} component={GenericNotFound} />
</Route>
For react-router 4 and 5
Keep the path
<Switch>
<Route exact path="/users" component={MyComponent} />
<Route component={GenericNotFound} />
</Switch>
Redirect to another route (change url)
<Switch>
<Route path="/users" component={MyComponent} />
<Route path="/404" component={GenericNotFound} />
<Redirect to="/404" />
</Switch>
The order matters!
I ma using Navigate to redirect from "/" to "/home"
import {BrowserRouter, Navigate, Route, Routes,} from "react-router-dom";
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Navigate to="/home"/>} />
</Routes>
</BrowserRouter>
how to get params using react router dom v5.0.1 before I could get parameters, but now I can't get them, what's the problem?
<BrowserRouter>
<Route path='/' exact component={Login} />
<Route path='/register' component={Register} />
<Route path='/home' component={Home} />
<Route path='/all/merchant' component={AllMerchant} />
<Route path='/detail/merchant/:id_merchant' exact component={DetailMerchant} />
<Route path='/detail/merchant/promo/:id_merchant' component={MerchantByPromo} />
<Route path='/promo/voucher/by/merchant/' component={MerchantByPromoDetail} />
<Route path='/all/category' component={Category} />
<Route path='/category/id/:category_id' component={CategoryById} render = {props => <CategoryById {...props} key={this.props.match.params} /> }/>
<Route path='/promo/grid/view' component={PromoGridView} />
{/* params not found */}
<Route path='/promo/grid/view/by/category/:category_id' component={AllPromoGridView} />
<Route path='/detail/promo/:voucher_id/category_id/:category_id' component={PromoGridViewDetail} />
{/* params not found */}
<Route path='/account' component={Account} />
</BrowserRouter>
According to the react-router doc, it should be accessible in your Component via the props match:
Example:
// the route
<Route path="/:id" component={Child} />
/*
...
*/
//the component
function Child({ match }) {
return (
<div>
<h3>ID: {match.params.id}</h3>
</div>
);
}
Another post to ask you about a "situation" I am having, which is disappointing as my Router is creating too many refreshs and for the point is actually not to have to refresh part of the page by using React.
I would like the following :
When I go to './' and there is no user connected it shows a homepage (without header and footer)
When I go to './' and I am connected or any other link whether I am connected ot not it should show the relevant page with a Header and a Footer.
So the fact of being not connected does not show header/footer is only true for the './' address.
How I solved it and it is not satisfying because it seems my header is rerendering all the time I change pages even between two pages with Router....
I have a first Router, the AppRouter :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
My index is like that :
export class Index extends React.Component {
render() {
if (this.props.user){
return (
<SubRouter />
)
} else {
return (
<Homepage />
)
}
}
}
So if no user the Homepage is showing if user it goes back to the SubRouter.
SubRouter is like that :
export class SubRouter extends React.Component {
(...)
render(){
return (
<div className="fullpage">
{this.state.inboxOpen ? <Inbox closeInbox={this.closeInbox} oneUserInboxId={this.state.oneUserInboxId} /> : undefined }
<Header openInbox={this.openInbox} closeInbox={this.closeInbox} />
<Switch>
<Route path="/" component={Dashboard} exact={true} />
<Route path="/admin" component={Admin} exact={true} />
<Route path="/account" component={Account} exact={true} />
<Route path="/settings" component={Settings} exact={true} />
<Route path="/faq" component={Faq} exact={true} />
<Route path="/cgv" component={Cgv} exact={true}/>
<Route path="/legal" component={Legal} exact={true}/>
<Route path="/login" component={Login} exact={true}/>
<Route path="/signup" component={Signup} exact={true}/>
<Route path="/notifications" render={() => (<Dashboard notifications={true} />)} exact={true} />
}} />
<Route path="/reset-password/:token" component={ResetPassword} />
<Route path="/forgot_password" component={ForgotPassword} exact={true} />
<Route path="/post/:postId" component={OnePost} />
<Route path="/*" component={NotFound} />
</Switch>
<Footer />
</div>
)
}
}
So this code is "working" but somehow we can see rerenders that should not happen, I am open to any idea to optimize this. Thanks in advance !
Problem was coming from here :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
Should not have rerendered SubRouter here as it is already rendered in HomePage. Good code is :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
What's wrong with my route structure? Used Link to navigate couldn't see the changes.
class App extends React.Component {
render() {
return(
<BrowserRouter>
<div>
<AuthRoute></AuthRoute>
<Switch>
<Route path='' component={Home} />
<Route path='/profile' component={Profile} />
</Switch>
</div>
</BrowserRouter>
)
}
}
https://codesandbox.io/s/r433m6kvvp
Changes:
1- Instead of path='' (blank path) use path='/'.
2- Use exact word with path='/' otherwise define that in that last, because if you don't use exact then / will match with /profile or any other route also.
Check the doc for more details about exact and Switch and how they work.
Like this:
<Route exact path='/' component={Home} />
<Route path='/profile' component={Profile} />
or
<Route path='/profile' component={Profile} />
<Route path='/' component={Home} />
Working Code.
This is our parent view:
http://localhost:8080/#/dashboard/
When I click on a link to Menu Navigation:
http://localhost:8080/#/dashboard/menu-navigation
This will load up the correct menu-navigation view, however if I refresh the app goes back to /dashboard instead of staying on menu-navigation.
From the main Routes.js
const Routes = () => (
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route path="/login" exact component={Login} />
<Route path="/redirect" component={FirebaseRedirector} />
<Route path="/restricted-access" component={RestrictedAccess} />
<Route path="/change-password/:hash?" component={ChangePassword} />
<Route path="/reset-password" exact component={ResetPassword} />
<Route path="/" component={Main} />
<Route path="*" component={NotFound} />
</Switch>
</ConnectedRouter>
</Provider>
);
export default Routes;
Note once you are logged in the Main component above is loaded:
render() {
return (
<Main
user={this.props.user}
signOut={this.signOut}
>
<Switch>
<Route
path="/dashboard/categories/unmatched-api/:id?"
component={CategoriesUnmatchedApi}
notExact
/>
<Route path="/dashboard/menu-navigation" exact component={MenuNavigation} />
<Route path="/dashboard/home-screen" exact component={HomeScreen} />
<Route path="/dashboard/categories/product-config" component={CategoryProductConfig} />
<Route path="/dashboard/categories/:category?" component={Categories} />
<Route path="/dashboard/playground" exact component={Playground} />
<Route path="/dashboard" exact component={Drafts} />
<Route path="/" exact component={Drafts} />
<Route path="*" component={NotFound} />
</Switch>
</Main>
);
}
Here is the state once you navigate to the MenuNavigation route
Then the state after refresh
Seems like react router is not respecting <Route path="/dashboard/menu-navigation" ?
I did notice after refresh that the Main.js route section gets hit 3 times, the first time the this.props.location is correct, however the next 2 times it's just /dashboard
Figured it out! We had a redirect to the /dashboard everytime.
Inside our login actions we had:
onAuthStateChange -> checkAuth which contained this:
dispatch(push(authDasboardView));
After removing the dispatch to authDashboardView, this fixed the problem!