2

I'm trying to change routes depending on logged in state:

  renderRouter() {
    if (loggedIn) {
      return (
        <Router>
          <Route path="/" component={Dashboard} />
        </Router>
      );
    }

    return (
      <Router>
        <Route path="/" component={Login} />
      </Router>
    );
  }

But when state changes I'm receiving a warning: Warning: [react-router] You cannot change <Router routes>; it will be ignored

Is it possible to reinitialize react-router with new routes?

I know that I could use onEnter to ensure that user has access to this page, but I need to have different components in one route according to logged in state and don't want to move such logic inside of components.

Eugene Tsakh
  • 2,777
  • 2
  • 14
  • 27

2 Answers2

2

First of all you create two Router, I don't think you should do this.

Try wrapping your Routes in a Switch component which is in only one Router, then use the render props of your "main" Route, which will redirect you if the condition is true, use exact props to be sure this Route will match by default, notice that your "/dashboard" Route is above the other, so the Switch can match it.

The result should be like this :

<Router>
  <Switch>
    <Route path="/dashboard" component={Dashboard} />
    <Route 
      path="/"
      exact
      render={() => {
        if (loggedIn) {
          return <Redirect to="/dashboard" />;
        }

        return <Login />;
      }}
    />
  </Switch>
</Router>

Don't forget to import the components.

Hope it helped.

Tomafa06
  • 110
  • 1
  • 1
  • 11
  • Good point about creating two routers. But this approach is still not what I need. I want to have completely different routes according to logged in state to exclude any possibility that user can reach secured endpoint in routing layer. Also I need to have 404 for all other secured endpoints if user is not logged in and it's not really cool to add render to each Route as for me. – Eugene Tsakh Jul 26 '17 at 10:14
  • Maybe a `withRouter` component can help you. Anyway, I think you can find what you want here : https://reacttraining.com/react-router/web/example/basic There are many useful examples of what you can do with react-router. I don't know everything about it, that's the best I can do for you, sorry. :( – Tomafa06 Jul 26 '17 at 10:31
0

I've tried few times to gain desired behavior and after all decided to change an approach of secure endpoints management. Components on my endpoints are very simple scenes which are just compose layer and some scene modules. So I've created a scene wrapper:

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Login from '../scenes/Login';

function Scene({ children, fallback, secure, auth }) {
  if (secure === auth) {
    return children;
  }
  return React.createElement(fallback);
}

Scene.propTypes = {
  children: PropTypes.node.isRequired,
  auth: PropTypes.bool,
  fallback: PropTypes.func,
  secure: PropTypes.bool,
};

Scene.defaultProps = {
  auth: false,
  fallback: Login,
  secure: false,
};

const mapStateToProps = ({ auth }) => ({ auth });

export default connect(mapStateToProps)(Scene);

And then in Dashboard scene:

import React from 'react';
import Scene from '../modules/Scene';
import Layout from '../components/Layout';

export default function Dashboard() {
  return (
    <Scene secure>
      <Layout>
        <Module1 />
        <Module2 />
      </Layout>
    </Scene>
  );
}
Eugene Tsakh
  • 2,777
  • 2
  • 14
  • 27