React-Router cannot access to the below routes

Viewed 91

I am making a simple login app. I have public and private routes. And I also have a variable route that can access to both private and public users. So far I created routes from public and private users. But that variable route for both users is not accessible. How can I solve this issue. I am using router-dom v5

     <Route path={"/forgot-password"}>
        <ForgetPwd />
      </Route>

      <Route path={"/verifyEmail"}>
        <EmailVarification />
      </Route>
      <Route path={"/recover-password"}>
        <Recoverpassword />
      </Route>
      <PostProvider>
        <Layout>
          <PrivateRoutes path="/dashboard">
            <Dashboard />
          </PrivateRoutes>
        </Layout>
      </PostProvider>
      <Route path="/:id?">
        <Publicpage />
      </Route>

I Think above question is not very clear. so I will explain my question more

  <BrowserRouter>
    <Switch>
      <Route path={"/home"}>
        <Home />
      </Route>
      <Route path={"/"}>
        {/* I need to add some logic to Protect these routes */}
        <Switch>
          <Route path={"/about"}>
            <About />
          </Route>
        </Switch>
      </Route>
     {/* This below route cannot access */}
      <Route path={"/:id"}>
        <PublicPage />
      </Route>
    </Switch>
  </BrowserRouter>

I want to create simple react-router but I need public page to display data according to entered code name. And also I need to have some protected routes also. So I created some protected routes and my variable public route placed end of the routes So it will not clash with static routes. My question is after that protected route, react-router is not looking outside that scope. Below routes are not rendered

1 Answers

Issue

I think I'm reading between the lines here and guessing/assuming that you are rendering these routes within a Switch component. If this is the case then the issue is that the only valid children components of the Switch are the Route and Redirect components. When the PostProvider component is reached, route matching ceases and the PostProvider component is returned/rendered.

Solution

Refactor/restructure the components to render the custom PrivatesRoutes component at the Switch component level so routes can continued to be matched and rendered. Move the PostProvider component inside the route.

Example:

<Switch>
  ... other more specific routes ...
  <Route path="/forgot-password">
    <ForgetPwd />
  </Route>
  <Route path="/verifyEmail">
    <EmailVarification />
  </Route>
  <Route path="/recover-password">
    <Recoverpassword />
  </Route>
  <PrivateRoutes path="/dashboard">
    <PostProvider> // <-- PostProvider moved into route
      <Layout>     // <-- Layout moved into route
        <Dashboard />
      </Layout>
    </PostProvider>
  </PrivateRoutes>
  <Route path="/:id?">
    <Publicpage />
  </Route>
  ... other routes ...
</Switch>

Update

<BrowserRouter>
  <Switch>
    <Route path={"/home"}>
      <Home />
    </Route>
    <Route path={"/"}>
      {/* I need to add some logic to Protect these routes */}
      <Switch>
        <Route path={"/about"}>
          <About />
        </Route>
      </Switch>
    </Route>
   {/* This below route cannot access */}
    <Route path={"/:id"}>
      <PublicPage />
    </Route>
  </Switch>
</BrowserRouter>

Within the Switch component path order and specificity matters. The less specific path="/" route is ordered before the "/:id" path, so "/" will always be matched and rendered and any routes listed after will effectively be unreachable.

Within Switch components you should order the routes by inverse order of path specificity. "/home" is more specific than "/:id" is more specific than "/", and this should be the order for these three routes.

<BrowserRouter>
  <Switch>
    <Route path="/home">
      <Home />
    </Route>
    <Route path="/:id}>
      <PublicPage />
    </Route>
    <Route path="/">
      <Switch>
        <Route path="/about">
          <About />
        </Route>
      </Switch>
    </Route>
  </Switch>
</BrowserRouter>

The same holds true when using custom route components.

Example PrivateRoute component:

const PrivateRoute = props => {
  // auth logic
  return isAuth ? <Route {...props} /> : <Redirect to="/login" />;
};

...

<BrowserRouter>
  <Switch>
    <Route path="/home">
      <Home />
    </Route>
    <PrivateRoute path="/about">
      <About />
    </PrivateRoute>
    <Route path="/:id}>
      <PublicPage />
    </Route>
  </Switch>
</BrowserRouter>
Related