14

I want to create a prefix for some paths in React Router v4, such as v1 in front of all my routes for version 1 of my app. Here's what I've tried:

<BrowserRouter>
  <Switch>
    <App path="v1" >
      <Switch>
        <Route path="login" component={Login} />
        <Route component={NotFound} />
      </Switch>
    </App>
    <Route component={NotFound}/>
  </Switch>
</BrowserRouter>

Here's App:

import React, { Component } from 'react';
import logo from '../Assets/logo.svg';
import '../Assets/css/App.css';

class App extends Component {
  render() {
     return (
       <div>
         {this.props.children}
       </div>
     );
  }
}

export default App;

Currently I am using this approach but it doesn't seem to working. When I go to http:\\localhost:3000\v1\login it shows the NotFound component. Any help here?

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
Lakshay Jain
  • 446
  • 1
  • 3
  • 17

3 Answers3

36

Came across a similar problem. Ended up using <BrowserRouter basename='/v2'> https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string

cusejuice
  • 10,285
  • 26
  • 90
  • 145
9

Instead of using App as a container, restructure your routes like so:

<BrowserRouter>
   <Switch>
      <Route path="/v1" component={App} />
      <Route component={NotFound}/>
   </Switch>
</BrowserRouter>

This will make App render whenever you navigate to /v1 or /v1/whatever. Then, in App, instead of rendering children, render your other routes:

render() {
  const { match } = this.props;

  return (
    <Switch>
      <Route path={`${match.url}/login`} component={Login} />
      <Route component={NotFound} />
    </Switch>      
  );
}

Thus, App will render a Switch with two possible routes. match.url here is v1 because it matched the URL part v1. Then, it creates a route with ${match.url}/login which results in v1/login. Now, when you navigate to v1/login you'll get the Login component.

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
  • ok , but is there any way where we can do it with in routing files instead of component files so my routing logic is more organized in routing folders? – Lakshay Jain Aug 03 '17 at 16:05
  • @LakshayJain I don't think so, unless you explicitly lay out each and every single possible route. In previous React Router versions, you could have nested routes to accomplish exactly what you want, but in v4, it's not possible unless you do it this way. – Andrew Li Aug 03 '17 at 16:07
  • So should i create layouts file for each prefix and use it as routing file like your answer? – Lakshay Jain Aug 03 '17 at 16:10
  • @LakshayJain It all depends. I would personally organize each versions into folders (such as v1, v2, etc). Then in `App`, use `require` to import dynamically such as `const Login = require(\`${match.url}/Login.js\`)`. – Andrew Li Aug 03 '17 at 16:12
  • Ok thanks for helping me i also figure out how to do the same with my approach with the help of your example.. I posted it in answer – Lakshay Jain Aug 03 '17 at 16:35
  • In the more general case, where the parent match may contain path params, it's better to use `path={\`${match.path}/login\`}` instead of `path={\`${match.url}/login\`}` to match subroutes. `match.url` might have a value like `/users/12345` whereas `match.path` will have a value like `/users/:userId`. If you want the inner match to provide the `userId` param, using `match.path` allows that inner router to pick up the params defined for the outer router. Pardon that terrible rhyme. – Luke Griffiths Mar 12 '20 at 20:34
4

If some one want to still use prefix in router file

import {BrowserRouter , Route , Switch } from 'react-router-dom';
import App from '../Components/v1/App';
import React from 'react';
import NotFound from '../Components/404';
import Login from '../Components/v1/Login'

var v1="/v1";

const IndexRoute = (
    <BrowserRouter>
            <Switch>
              <App path={v1}>
                  <Switch>
                    <Route path={`${v1}/login`} component={Login} />
                    <Route component={NotFound} />
                  </Switch>
              </App>
              <Route component={NotFound} />
            </Switch>
    </BrowserRouter>
  );
export default IndexRoute;
Lakshay Jain
  • 446
  • 1
  • 3
  • 17