2

All of my main react components have some parts like this:

export default class ExampleMain extends Component {
    constructor(props) {
        super(props)
        this.state = {
            isAuthenticated: Meteor.userId() !== null
        }
    }

    componentWillMount() {
        if (!this.state.isAuthenticated) browserHistory.push('/login')
    }
    componentDidUpdate() {
        if (!this.state.isAuthenticated) browserHistory.push('/login')
    }
}

With this I am checking if a user is logged in. If this is false, the user will be redirected to login route. As this part is used in many components, I was thinking if I can optimize this to get a DRY code...

Update

I am using react router:

render((
    <Router history={ browserHistory }>
        <Route path='/' component={ App }>
            <IndexRoute component={ Main } />
            <Route path='login' component={ Login } />
            <Route path='content/:id' component={ Content } />
        </Route>
        <Redirect from='*' to='/' />
    </Router>
), document.getElementById('root'))
5
  • Are you using Redux/React-Router? Commented Feb 9, 2017 at 21:24
  • I am using react router Commented Feb 9, 2017 at 21:25
  • You can check it once then, in the constructor of the component that is in a Route that is the parent of all of these components. Commented Feb 9, 2017 at 21:27
  • I've updated the question to show you my routing example... So you mean to check on the App component, right? Commented Feb 9, 2017 at 21:30
  • 1
    Yes. You can use onEnter hook as well, and make that logic and redirect even before you render the App component. But since login route is nested, hook won't help you too much unless you change your routes order. (since App would have to be rendered anyway, you might want login to be outside) Commented Feb 9, 2017 at 21:34

2 Answers 2

2

You can try something like this:

<Router history={ browserHistory }>
    <Route path='/' component={ App }>
        <IndexRoute component={ Main } />
        <Route path='/login' component={ Login } />
        <Route path='content/:id' component={ Content } />
    </Route>
    <Redirect from='*' to='/' />
</Router>

And in App, using withRouter to "inject" the router inside your component:

import { withRouter } from 'react-router';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isAuthenticated: Meteor.userId() !== null
        }
    }

    componentWillMount() {
        if (!this.state.isAuthenticated) {
           this.props.router.push('/login');
        }
    }
}

export default withRouter(App);
Sign up to request clarification or add additional context in comments.

5 Comments

just asking... App is my main component, which gives me the wrapping main layout. This is always the same (navigation bar, background image, and so on). Also on login page. So I think I have to render App and do the authenfication for all other components...
You know your app's needs best, disregard my Login route suggestion then and get it back nested in App. I'll edit.
Close to working... But if user is logged out I get the error Warning: setState(...): Cannot update during an existing state transition
@user3142695 Did this work out eventually or are you still getting that error ?
Can you try moving the if (isAutheniticated chunk to componentWillMount instead of the constructor?
1

Maybe this helps you. I would tried to use any hook before routing. But you always can extend your own class with such functionality like that example

function requireAuth(nextState, replace) {
  if (!auth.loggedIn()) {
    replace({
      pathname: '/login',
      state: { nextPathname: nextState.location.pathname }
    })
  }
}

render((
  <Router history={ browserHistory }>
    <Route path='/' component={ App }>
      <IndexRoute component={ Main } />
      <Route path='login' component={ Login } />
      <Route path='content/:id' component={ Content } onEnter={requireAuth} />
    </Route>
    <Redirect from='*' to='/' />
  </Router>
), document.getElementById('root'))

To see full code follow link above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.