My App.js
looks so ugly with a lot of routes and show/hide Navbar
component in some pages. What is a best practice to centralized routes and somehow refactor this show/hide Navbar
? Any suggestions? I did some research, but can not determine which way is better.
function App() {
const location = useLocation();
return (
<div className="App">
{splash ? <Splash /> : null}
{loading && !splash ? <Loading /> : null}
<Switch>
<ProtectedRouter exact path={"/"} component={Home} />
<Route exact path={"/signin"} component={SignIn} />
<Route exact path={"/signup"} component={SignUp} />
<Route exact path={"/signup/password"} component={SignUpPassword} />
<Route exact path={"/auth"} component={SignInSignUp} />
<Route exact path={"/forget-password"} component={ForgetPassword} />
<ProtectedRouter exact path={"/sessions"} component={Sessions} />
<ProtectedRouter exact path={"/awards"} component={Awards} />
<ProtectedRouter exact path={"/award-details"} component={AwardDetails} />
<ProtectedRouter exact path={"/features"} component={Features} />
<ProtectedRouter exact path={"/challenges"} component={Challenges} />
<ProtectedRouter exact path={"/videos"} component={Videos} />
<ProtectedRouter exact path={"/help"} component={Help} />
<ProtectedRouter exact path={"/performance"} component={Performance} />
<ProtectedRouter exact path={"/profile"} component={Profile} />
<ProtectedRouter exact path={"/pathways"} component={PathwayCatalog} />
<ProtectedRouter exact path={"/exercises"} component={Exercises} />
<ProtectedRouter exact path={"/stats"} component={Stats} />
<ProtectedRouter exact path={"/notifications"} component={Notification} />
{/* PUBLIC SHARE PAGES */}
<Route exact path={"/stats/share"} component={StatsShare} />
<Route exact path={"/exercises/share"} component={ExercisesShare} />
<Route exact path={"/performance/share"} component={PerformanceShare} />
<Route exact path={"/awards/share"} component={AwardsShare} />
<Route exact path={"/award-details/share"} component={AwardsDetailsShare} />
</Switch>
{location.pathname === "/signup" ||
location.pathname === "/signup/password" ||
location.pathname === "/auth" ||
location.pathname === "/features" ||
location.pathname === "/forget-password" ||
location.pathname === "/help" ||
location.pathname === "/skillset" ||
location.pathname === "/pathways" ||
location.pathname === "/stats/share" ||
location.pathname === "/exercises/share" ||
location.pathname === "/performance/share" ||
location.pathname === "/awards/share" ||
location.pathname === "/award-details/share" ||
location.pathname === "/notifications" ||
location.pathname === "/notifications" ||
location.pathname === "/signin" ? null : (
<Navbar />
)}
</div>
);
}
CodePudding user response:
You can make an array and put all the required fields in it.
const Routes = [
{isProtected: true, path: "/", component: Home},
{isProtected: false, path: "/signin", component: SignIn},
{isProtected: false, path: "/signup", component: SignUp},
{isProtected: false, path: "/signup/password", component: SignUpPassword},
{isProtected: false, path: "/auth", component: SignInSignUp},
{isProtected: false, path: "/forget-password", component: ForgetPassword},
{isProtected: true, path: "/sessions", component: Sessions},
];
Then use this array in your switch statement.
<Switch>
{
Routes.map((route, index) => {
return(
route.isProtected? (
<ProtectedRouter exact path={route.path} component={route.component} />
) : (
<Route exact path={route.path} component={route.component} />
)
)
})
}
</Switch>
CodePudding user response:
- You only need to render
null
if the ternary IS the return of the component. Inside you can use logical AND&&
to conditionally render content inside the JSX. - Inside the
Switch
path order and specificity matter. Order the routes from more specific paths to less specific paths. If ordered correctly that is essentially a ZERO need for theexact
prop. - In
react-router-dom
v4/5Route
components can take an array of path strings. You can create an array of paths you want theNavbar
to render on. Render theNavbar
into a Route with the array of path strings and use theexact
prop here to prevent accidental root/sub-route matching. Here theexact
prop is used to be more explicit about the matching.
Suggested refactor:
const navbarPaths = [
"/signup/password",
"/signup",
"/auth",
"/features",
"/forget-password",
"/help",
"/skillset",
"/pathways",
"/stats/share",
"/exercises/share",
"/performance/share",
"/awards/share",
"/award-details/share",
"/notifications",
"/notifications",
"/signin",
];
function App() {
return (
<div className="App">
{splash && <Splash />}
{loading && !splash && <Loading />}
<Switch>
<Route path="/signin" component={SignIn} />
<Route path="/signup/password" component={SignUpPassword} />
<Route path="/signup" component={SignUp} />
<Route path="/auth" component={SignInSignUp} />
<Route path="/forget-password" component={ForgetPassword} />
<ProtectedRouter path="/sessions" component={Sessions} />
<Route path="/awards/share" component={AwardsShare} />
<ProtectedRouter path="/awards" component={Awards} />
<Route path="/award-details/share" component={AwardsDetailsShare} />
<ProtectedRouter path="/award-details" component={AwardDetails} />
<ProtectedRouter path="/features" component={Features} />
<ProtectedRouter path="/challenges" component={Challenges} />
<ProtectedRouter path="/videos" component={Videos} />
<ProtectedRouter path="/help" component={Help} />
<Route path="/performance/share" component={PerformanceShare} />
<ProtectedRouter path="/performance" component={Performance} />
<ProtectedRouter path="/profile" component={Profile} />
<ProtectedRouter path="/pathways" component={PathwayCatalog} />
<Route path="/exercises/share" component={ExercisesShare} />
<ProtectedRouter path="/exercises" component={Exercises} />
<Route path="/stats/share" component={StatsShare} />
<ProtectedRouter path="/stats" component={Stats} />
<ProtectedRouter path="/notifications" component={Notification} />
<ProtectedRouter path="/" component={Home} />
</Switch>
<Route path={navbarPaths} exact component={Navbar} />
</div>
);
}
Like the other answer, if you wanted to extract the route rendering you could specify them into an array and map them.
Example:
const routes = [
{
path: "....."
private: true|false,
component: ComponentReference
// ... any other route props
},
...
];
...
function App() {
return (
<div className="App">
{splash && <Splash />}
{loading && !splash && <Loading />}
<Switch>
{routes.map(({ private, ...routeProps }) => {
const RouteWrapper = private ? ProtectedRouter : Route;
return <RouteWrapper key={routeProps.path} {...routeProps} />;
})}
</Switch>
<Route path={navbarPaths} exact component={Navbar} />
</div>
);
}