Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separate Log In page using HashRouter in React

I would like to add a log in page that doesn't have App as a parent. This is my current HashRouter setup:

  <Provider store={ store }>
    <HashRouter>
      <App>
        <Route path='/path1' component={ Component1 } />
        <Route path='/path2' component={ Component2 } />
        <Route path='/path3' component={ Component3 } />
      </App>
    </HashRouter>
  </Provider>

If I do this:

  <Provider store={ store }>
    <HashRouter>
      <div>
        <Route path='/login' component={ Login } />
        <App>
          <Route path='/path1' component={ Component1 } />
          <Route path='/path2' component={ Component2 } />
          <Route path='/path3' component={ Component3 } />
        </App>
      </div>
    </HashRouter>
  </Provider>

Then I get the login page above the App. Here's my App Component:

const App = ({ children }) => (
  <div>
    <Navbar/>
    <div className='col-md-10 col-md-offset-1'>
      { children }
    </div>
  </div>
)

What's the best way to get a login path with a Login component, that doesn't include the App?

like image 860
Wylliam Judd Avatar asked Mar 29 '17 22:03

Wylliam Judd


People also ask

What is the use of Hashrouter in react?

A <Router> that uses the hash portion of the URL (i.e. window. location. hash ) to keep your UI in sync with the URL.

Does react Router code split?

One great benefit to using create-react-app is that it gives us code splitting and chunking out of the box. Chunks allow us to separate our codes into bundles, which are a group of related chunks packaged into a single file. Tools such as Create React App, Gatsby, and Next. js use webpack to bundle applications.


2 Answers

Since you are using react-router v4, you need to put your nested routes inside the parent component instead of nesting routes. See this answer for the explanation.

In your case, the simplest approach would be something like this.

<Provider store={ store }>
  <HashRouter>
    <div>
      <Switch>
        <Route path='/login' component={ Login } />
        <Route path='/' component={ App } />
      </Switch>
    </div>
  </HashRouter>
</Provider>

const App = () => (
  <div>
    <Navbar/>
    <div className='col-md-10 col-md-offset-1'>
      <Route path='/path1' component={ Component1 } />
      <Route path='/path2' component={ Component2 } />
      <Route path='/path3' component={ Component3 } />
    </div>
  </div>
)

Notice that how I have used <Switch> to wrap the '/login' and '/' routes. This will make sure that it only renders the first matching route from the given routes according to given order. So when the path is '/login', it will only render Login page even though it also matches(not exact match, you need to use 'exact' attribute for an exact match) the '/' route.

Update:

Above method is the recommended approach in react-router documentation. But if you see a value in keeping all your routes in one place, you can still use <Switch> with what you already have.

<Provider store={ store }>
  <HashRouter>
    <div>
      <Switch>
        <Route path='/login' component={ Login } />
        <App>
          <Route path='/path1' component={ Component1 } />
          <Route path='/path2' component={ Component2 } />
          <Route path='/path3' component={ Component3 } />
        </App>
      </Switch>
    </div>
  </HashRouter>
</Provider>
like image 63
Tharaka Wijebandara Avatar answered Nov 10 '22 04:11

Tharaka Wijebandara


You can use different layouts with a very basic main layout.

routes.js

export default () => (
    <Route path="/" component={Layout}>
        <Route component={WebLayout}>
            <IndexRoute component={Home} />
        </Route>
        <Route component={AppLayout}>
            <Route path="account" component={Account} />
        </Route>
        <Route component={SecurityLayout}>
            <Route path="login" component={Login} />
        </Route>
    </Route>
);

layout.js

const Layout = ({ children }) => (
    <div>
        {children}
    </div>
);

applayout.js

const AppLayout = ({ children }) => (
    ...
);

securitylayout.js

const SecurityLayout = ({ children }) => (
    ...
);
like image 43
Austin Winstanley Avatar answered Nov 10 '22 05:11

Austin Winstanley