Home > Software engineering >  How Can I refactor my App.js page routes in React ? What is the best practice for that?
How Can I refactor my App.js page routes in React ? What is the best practice for that?

Time:12-23

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:

  1. 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.
  2. 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 the exact prop.
  3. In react-router-dom v4/5 Route components can take an array of path strings. You can create an array of paths you want the Navbar to render on. Render the Navbar into a Route with the array of path strings and use the exact prop here to prevent accidental root/sub-route matching. Here the exact 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>
  );
}
  • Related