I'm working on a React app and i'm trying to figure out a better way to redirect to 404 page not found when user hits a wrong path.
Basically my application has a navbar with three main routes (Home, Content, Permissions) and a default redirect to render a route that displays 404 page not found:
<Switch>
<Route path="/home" component={Home} />
<Route path="/content" component={Content} />
<Route path="/permissions" component={Permissions} />
<Route path="/not-found" component={PageNotFound} />
<Redirect to="/not-found" />
</Switch>
My problem is with the /Permissions route because this one has many subroutes to display multiple configuration pages and i need to fetchData with a hook, so if the user goes to a wrong path it needs to wait for data fetching before being redirected to page not found:
const Permissions = () => {
const {isFetchingData} = usePermissionsData();
if(isFetchingData) {
return <Loading />;
}
return (
<div className={styles.permissions} >
<div className={styles.leftMenu} >
<LeftMenu />
</div>
<div className={styles.content} >
<Switch>
<Route path="/permissions" component={PermissionsWelcome}
<Route path="/permissions/users" component={UsersPermissions}
<Route path="/permissions/content" component={ContentPermissions}
<Route path="/permissions/dashboard" component={DashboardPermissions}
<Redirect to="/not-found" />
</Switch>
</div>
</div>
);
}
So my question is if it exists a better way to redirect the user to a page not found without needing to wait for the data fetching? (something that i consider is a waste of proccesing).
Any suggestion is welcome!
"A better way" can be subjective, but to help with the objective issue of needing to match a route before checking permissions then I suggest inverting control. By this I mean you should create a custom Route
component that will be matched first then check the permissions. It's not clear if your code snippet is a simplified version, but I assume the hook probably also determines if a user has permission to access the current route/resource. If there is an additional check for this then you can conditionally render a Route
with the current props or you can render a Redirect
to "bounce" the user off the route since they are missing required permission(s).
Example:
const PermissionRoute = props => {
const {isFetchingData} = usePermissionsData();
if(isFetchingData) {
return <Loading />;
}
return <Route {...props} />;
};
Permissions
const Permissions = () => {
return (
<div className={styles.permissions} >
<div className={styles.leftMenu} >
<LeftMenu />
</div>
<div className={styles.content} >
<Switch>
<PermissionRoute path="/permissions/users" component={UsersPermissions} />
<PermissionRoute path="/permissions/content" component={ContentPermissions} />
<PermissionRoute path="/permissions/dashboard" component={DashboardPermissions} />
<PermissionRoute path="/permissions" component={PermissionsWelcome} />
<Redirect to="/not-found" />
</Switch>
</div>
</div>
);
}
Main Routing
<Switch>
<Route path="/home" component={Home} />
<Route path="/content" component={Content} />
<Route path="/permissions" component={Permissions} />
<Route path="/not-found" component={PageNotFound} />
<Redirect to="/not-found" />
</Switch>