React-native-router-flux: protected scenes

Created on 21 Jul 2016  Â·  22Comments  Â·  Source: aksonov/react-native-router-flux

Version

Tell us which versions you are using:

  • react-native-router-flux v3.31.1
  • react-native v0.28.0

I don't know if this is an enhancement request or a question because I couldn't find any concrete info on docs/issues/source..

I'm trying to protect some views of my app under some logged in schema, is there any way to accomplish it with 'react-native-router-flux'?

question

Most helpful comment

@enapupe I found your solution is perfectly ! It works.

All 22 comments

Well you as the developer control when a user can see a certain screen. I'll leave this open for anyone who wants to post how they handle authentication in their apps, but in the simplest case it is if(isLoggedIn) { Actions.nextScreen(); }

Where would you do such call? Ideally you'd have a central point where you define which routes are protected under login. I did a small middleware but I couldn't avoid protected scenes from being rendered (before calling Actions.pageLogin()). Also, when I hit the back button at the login screen, it returns to the protected route, not to the initial.. so, there is also that.

The code I have right now:

import {Actions, ActionConst} from 'react-native-router-flux'

export default (store) => (next) => (action) => {
  console.log(store, store.getState(), action)
  if (action.type === ActionConst.FOCUS){
    const {needLogin} = action.scene
    const {user} = store.getState()
    if (needLogin && !user.get('authToken')) {
      action = Actions.pageLogin
    }
  }
  return next(action)
}


It seems that FOCUS happens after PUSH/REPLACE/etc, so, it won't prevent the transition. If I act in PUSH/REPLACE/etc I don't have access to scene..

I guess my confusion is - who are you protecting it from? It's not like the web where a user can craft a URL. You are in control of what's rendered.

When you log someone out, you can send them to the login page with Actions.pageLogin({type: "reset"}) and the stack is cleared. In other places, if you don't want someone to be able to go to a page, disable the button (or don't even render it) unless they're logged in.

I have a few routes in the app which are not accessible to unlogged users..
I thought that I could centralize this verification with scene
components. You are telling my I can't and I should do manual checks every
time I would have a call to any of these scenes?

On Fri, Jul 22, 2016 at 2:06 PM, Chris Ridenour [email protected]
wrote:

I guess my confusion is - who are you protecting it from? It's not like
the web where a user can craft a URL. You are in control of what's rendered.

When you log someone out, you can send them to the login page with Actions.pageLogin({type:
"reset"}) and the stack is cleared. In other places, if you don't want
someone to be able to go to a page, disable the button (or don't even
render it) unless they're logged in.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/aksonov/react-native-router-flux/issues/953#issuecomment-234599728,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AARxCu_h4ewAH4NEtQslP3zXZ2ld7YsDks5qYPiqgaJpZM4JSA6f
.

I think I got your point.. I could just create a function over Actions, do some dirty checks there and stop using react-native-router-flux's Actions

Correct - if your goal is to just reduce boilerplate code, I would just use a standard JS function.

Now I have another question, how can I remove pageLogin from history stack? I think replace does the job but it doesn't respect the animation..

I've got the following code to handle routes: (I'm pasting it just in case anyone has similar needs)

import {Actions} from 'react-native-router-flux'
import {user} from '../config/user'

const FORBIDDEN = ['somePage', 'otherPage']

const _isLoggedIn = () => {
  return !!user.authToken
}

const _navigate = (route, params) => {
  if (FORBIDDEN.includes(route) && !_isLoggedIn()) {
    Actions.pageLogin({params: {route, params}})
    return
  }
  Actions[route](params)
}

const Router = {
  push (scene, params = {}) {
    params.type = 'push'
    _navigate(scene, params)
  }
  , replace (scene, params = {}) {
    params.type = 'replace'
    _navigate(scene, params)
  }
  , go (scene, params = {}) {
    _navigate(scene, params)
  }
  , pop () {
    Actions.pop()
  }
}

export default Router

And login component has this connect:

const mapStateToProps = (state, {params}) => {
  if (someIndicatorsOfLogin) {
    if (params.route){
      Router.replace(params.route, params.params)
    }
    [...]


If I use a regular push it animates correctly but pop would go back to page login

If you want the push animation, you can use the unmountScene prop introduced just last week in #932

So if I register login scene with that prop it would not persist in the history stack?

I actually think I might have led you down the wrong path.

At some point, I had a fork with an Actions.reset() - let me see if I can find it as it would do what you want. There are also some issues to remove certain scenes from the stack by name.

hey @cridenour, do you think is possible to propose a change like this? https://github.com/aksonov/react-native-router-flux/compare/master...enapupe:ActionsProto?expand=1

I modified the prototype of Actions[key] in order to have access to the scene props. This is very useful in this auth scenario where I'd like to simple add a propType like <Scene key="someKey" forbidden={true} /> and have access just with Actions.someSceneKey.forbidden

Interesting! I personally don't see any issues with it - I'd say go ahead and open a PR and see what others think.

Just for the record: there is some new function get in Actions so you can do Actions.get( 'someKey') and have the necessary access to the props.. But it seems to be buggy as it is not finding my scenes.
So, there is not need for that PR once this get functionality is OK.

It is strange, because it uses the same algorithm as REFRESH. If refresh can found your scenes then this method should too.

On 26 Jul 2016, at 19:56, Iacami Gevaerd [email protected] wrote:

Just for the record: there is some new function get in Actions so you can do Actions.get( 'someKey') and have the necessary access to the props.. But it seems to be buggy as it is not finding my scenes.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub https://github.com/aksonov/react-native-router-flux/issues/953#issuecomment-235351139, or mute the thread https://github.com/notifications/unsubscribe-auth/ABQpceCYI7JAPWaJd6AkP50_p723aqSjks5qZkpggaJpZM4JSA6f.

My navigationState has only ONE children, while it should have many because my Scene schema has many.

My guess is https://github.com/aksonov/react-native-router-flux/blob/master/src/State.js#L69 is not right OR I'm just not using the router as I was supposed to 😞

This is the Scene schema I'm running:

<Router sceneStyle={styles.scene} style={styles.tabBar}>
  <Scene
    key="root"
    animationStyle={this.defaultInterpolator}
    passProps={true}
    titleStyle={styles.navTitle}
    navigationBarStyle={styles.navigationBar}
    leftButtonIconStyle={styles.leftButton}
  >

    <Scene key="drawer" component={NavigationDrawer}>
      <Scene key="drawerChildrenWrapper">
        <Scene key="pageBrowse" component={PageBrowse} title="Browse" initial />
        <Scene authOnly={true} key="pageMy" component={PageMy} title="My" />
      </Scene>
    </Scene>

    <Scene key="pageAbout" component={PageAbout} title="About" />
    <Scene key="pageOrder" component={PageOrder} title="Details" />
    <Scene key="pageCatalogSubcategories" component={PageCatalogSubcategories} />
    <Scene key="pageCatalogEquipment" component={PageCatalogEquipment} />
    <Scene key="pageEquipment" component={PageEquipment} />
    <Scene authOnly={true} key="pageRent" direction="vertical" onBack={noop} hideBackImage={true} component={PageRent} />
    <Scene key="pageLogin" title="Login" component={PageLogin} />
    <Scene key="pageRegister" title="Register to Rent" component={PageRegister} />
    <Scene authOnly={true} key="pageProfile" title="Edit Profile" component={PageProfile} />

  </Scene>
</Router>

refresh uses a different function: https://github.com/aksonov/react-native-router-flux/blob/master/src/Router.js#L91

But yeah, refresh seems to be working just fine!

@enapupe Have you get the answer? I meet the same require as yours. Do you have some better solutions?

@jacobcyl what exactly do you need? there's many things going on here..
I can advance that I ended giving up many things to be able to deliver the basic navigation (without bugs). Far from ideal.

@enapupe well, I want to intercept loading scene to check authentication first. How do u
solve your problem. If I create a function to handle Actions like what you mentioned above, for example check if user logged in or not , if not jump to login scene. But if logged in and pop back to the prev scene how to remove the login scene in the navigate state?

@enapupe I found your solution is perfectly ! It works.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

basdvries picture basdvries  Â·  3Comments

sarovin picture sarovin  Â·  3Comments

rafaelcorreiapoli picture rafaelcorreiapoli  Â·  3Comments

sreejithr picture sreejithr  Â·  3Comments

vinayr picture vinayr  Â·  3Comments