0

I'm trying to do layouts with react-router.

When my user hits / I want to render some layout. When my user hits /login, or /sign_up I want the layout to render, with the relevant component for /login or /sign_up rendered.

Currently, my App.js looks like this

return (
  <div className={className}>
    <Route path="/" component={Auth} />
    <ModalContainer />
  </div>
);

My Auth.js looks like this

return (
  <AuthFrame footerText={footerText} footerClick={footerClick}>
    <Route path="/login" component={LoginContainer} />
    <Route path="/sign_up" component={SignUpContainer} />
  </AuthFrame>
);

So AuthFrame will get rendered when I hit /, and then react router looks for login or sign_up to render the other containers.

However, when I hit /, only the AuthFrame will render.

I would like for / to be treated as /login.

How do I achieve this?

praks5432
  • 7,246
  • 32
  • 91
  • 156
  • so your problem is not about rendering layout, but rather how to make `react-router` render your `Login` component inside `AuthFrame` both for `/` and `/login` routes, do I understand you correctly? If that's the case, take a look at [Multiple path names for a same component in React Router](https://stackoverflow.com/questions/40541994/multiple-path-names-for-a-same-component-in-react-router) on SO. – margaretkru Jan 06 '18 at 11:03

3 Answers3

0

I think you're forced to introduce a prop/state which indicates the status of your viewer. This means is he signed in or just a guest of your website.

Your router can't obviously render /login if you you hit / but the router allows you to redirect to another page:

class AuthContainer extends React.Component {
    defaultProps = {
        loggedIn: false
    }

    render() {

        return <div>
            <Route path="/login" component={LoginContainer}/>
            <Route path="/sign_up" component={SignUpContainer}/>
        </div>
    }
}

class PublicHomePage extends React.Component {
    render() {

        return <div>
            <Route path="/settings" component={SettingsComponent}/>
            <Route path="/profile" component={ProfileComponent}/>
            <Route path="/and_so_on" component={AndSoOnComponent}/>
        </div>
    }
}


class App
    extends React.Component {
    defaultProps = {
        loggedIn: false
    }

    render() {

        const {loggedIn} = this.props;

        if (loggedIn) {
            return <PublicHomePage/>
        }


        return <Route exact path="/" render={() => (
            <Redirect to="/login"/>
        )}/>


    }
}

I hope this code works for you. It isn't quite perfect but it should give you an idea how you could solve your problem.

Felix
  • 2,531
  • 14
  • 25
0

In your case I would probably manipulate a bit with Routes in react-router. This code in AuthFrame should do the trick:

return (    
    <AuthFrame footerText={footerText} footerClick={footerClick}>
         {["/", "/login"].map((path, ind) =>
            <Route exact key={ind} path={path} component={LoginContainer} />
         )}
         <Route exact path="/sign_up" component={SignUpContainer} />
    </AuthFrame>);

Note the usage of exact on the routes, this is to prevent matching login component on /sign_up since it will also match / and prevent rendering both login and signup when accessing the root path (/).

margaretkru
  • 2,751
  • 18
  • 20
0

The Switch component is useful in these cases:

return (
  <AuthFrame footerText={footerText} footerClick={footerClick}>
    <Switch>
      <Route path="/login" component={LoginContainer} />
      <Route path="/sign_up" component={SignUpContainer} />
      {/* Default route in case none within `Switch` were matched so far */}
      <Route component={LoginContainer} />
    </Switch>
  </AuthFrame>
);

see: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md

sphire
  • 436
  • 3
  • 5