How can I split React Router into multiple files

Viewed 10974

My routes file is getting rather messy so I decided to split them out into separate files.

My problem is that if I used 2 separate files, whichever comes after the first include does not get rendered:

const routes = (
  <div>
    <Switch>
      <Route exact path="/" component={Home} />
      {Registration} //Does get rendered

      //Everything below this does not get a route
      {Faq}
      <Route path="/login" component={login} />
      <Route component={NoMatch} />
    </Switch>
  </div>
);

If I switch Faq with registration then all the Faq routes will work.

RegistrationRoutes.js

import Introduction from '../containers/Registration/Introduction';
import Login from '../containers/Login';

const Routes = (
  <Switch>
    <Route path="/login" component={Login} key="login" />,
    <Route path="/registration/introduction" component={Introduction} key="registration-intro" />
  </Switch>
);
export default Routes;

FaqRoutes.js

import Faq from '../containers/Faq';
import faqJson from '../json_content/faq/faq';
import FaqCategory from '../containers/Faq/faqCategory';

const Routes = (
  <Switch>
    <Route path="/faq/:category" component={FaqCategory} key="faqCat" />
    <Route path="/faq" render={props => <Faq data={faqJson} />} key="faq" />
  </Switch>
);
export default Routes;
3 Answers

May be you can move them to config file and load them from there.

App.tsx

import routes from "./routes";
const App: React.FC = () => {
  return (
      <BrowserRouter>
        <div>
          <Switch>
            {routes.data.map((entry) => {return (<Route {...entry}/>)})}
          </Switch>
        </div>
      </BrowserRouter>
  );
};

export default App;

router.ts

const routes = {data: [
        {
            key: "one",
            path: "/three"

        },
        {
            key: "two",
            path: "/two"
        }
    ]
}

export default routes;

This will keep your code simple

Your code would get translated to something like this,

const routes = (
  <div>
    <Switch>
      <Route exact path="/" component={Home} />
      <Switch>
         <Route path="/login" component={Login} key="login" />,
         <Route path="/registration/introduction" 
             component={Introduction} key="registration-intro" />
      </Switch>

      //Everything below this does not get a route
      {Faq}
      <Route path="/login" component={login} />
      <Route component={NoMatch} />
    </Switch>
  </div>
);

This is wrong way to implement routing with react-router-dom or React-Router v4.

For Correct way of implementation You can see this example.

index.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";

import LandingPage from "../Registration";

const Home = () => {
  return <div>
  Home Component
   <Link to="/auth/login">Login</Link>
  </div>;
};

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <BrowserRouter>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/auth" component={LandingPage} />
        </Switch>
      </BrowserRouter>
    </div>
  ); 
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Registration.js

import React, { Component } from 'react';
import { Switch, Route, Link, Redirect } from 'react-router-dom';
const LoginRegister = (props) => {
  return (
    <div>
      Login or register
    <Link to="/login">Login</Link>
      <br />
      <Link to="/signup" >Signup</Link>
    </div>
  );
}

const Login = (props) =>{
  console.log("login ", props);
  return (
    <div>
      Login Component
    <Link to="/auth/signup" >Signup</Link>
    </div>
  );
} 

const Signup = () => (
  <div>
  Signup component
    <Link to="/auth/login" >Login</Link>
  </div>
);

class LandingPage extends Component {

  render() {
    console.log('Landing page',this.props);
    const loginPath = this.props.match.path +'/login';
    const signupPath = this.props.match.path + '/signup';
    console.log(loginPath);
    return (
      <div className="container" >
      Landing page
        <Switch>
          <Route path={loginPath} component={Login} />
          <Route path={signupPath} component={Signup} />
          <Route path="/" exact component={LoginRegister} />
        </Switch>
      </div>
    );
  }

}

export default LandingPage;

Try the following

RegistrationRoutes.js

import Introduction from '../containers/Registration/Introduction';
import Login from '../containers/Login';

const Routes = (
  <React.Fragment>
    <Route path="/login" component={Login} key="login" />,
    <Route path="/registration/introduction" component={Introduction} key="registration-intro" />
  </React.Fragment>
);
export default Routes;
Related