Hi,
I have small question about scenes stack modification.
In my application, for example, user moves from screen1 to screen4 like that:
screen1 => screen2 => screen3 => screen4
Then user should move from screen4 to screen5. Once he does that I want him to be unable to move back to screen3 or screen4. If he goes back I want him to move to screen2. In other words I want my scene stack become like that:
screen1 => screen2 => screen5
I want to remove screen3 and screen4 from scenes stack. Right now I do it following way: on screen4 I run code:
Actions.popTo('screen2');
Actions.screen5();
But in that case I see unnecessary animation of removing screens and then opening new one. I tried to to do it like that:
Actions.popTo('screen2', {duration: 0});
but I still see animation.
So, the question: is there any way to remove scenes from stack without any visual changes on phone screen?
What about Actions.popTo('screen2') when the user leaves the screen5 ? Seems easier
@Blapi The example is very simplified version of what is really happens in application. The number of screens to remove decided by separate logic depends on data received from server on screen4. And I don't want to "remember" that decision inside screen5 which is have separate complex logic. Also I don't want to control back button on screen5, user can do it with Andoid hardware button.
Not really happy about this hack because I find this ugly but you could do that :
In your app.js (or wherever your Router is located), add this :
const reducerCreate = (params) => {
const defaultReducer = new Reducer(params)
return (state, action) => {
// console.log('Action :', action)
// console.log('State :', state)
if (state.routes[state.routes.length - 1].routeName === 'theSceneThatTriggerMyAction') {
state.routes.index -= numberOfScenesIWantToRemove
state.routes.splice(indexOfTheSceneToStartRemovingTheScenes, numberOfScenesIWantToRemove)
}
return defaultReducer(state, action)
}
}
And then your Router should look like this :
<Router
backAndroidHandler={this.onBackPress}
createReducer={reducerCreate}>
You can do your stuff even if I'm not a huge fan of this trick, but you will just need to adapt your logic of course.
If you have a data coming from the server, you can fetch it within state.routes[state.routes.length - 1].params.dataFetchedFromTheServer (all the params you send to a scene will be there) so you could use this to adapt your logic.
@Blapi yep, looks ugly, but if that is the only way to manage the stack, then probably I have no choice.
By the way, If I change the stack that way, will removed screens be unloaded? In other words: will function componentWillUnmount() be called for them?
I don't know, I haven't checked
@Blapi I have tried code that you suggested.
Good thing: componentWillUnmount is called for removed screens.
Bad thing: I still see animation of removing these screens before new screen5 appears.
What's the status now?
@Blapi now?
Yes, is it working well? Did you find a workaround?
@Blapi Yes, it working, but I still see screen removing animation, like if I'm calling Actions.popTo('screen2');. And currently I didn't found a workaround.
Unfortunately it is how react navigation works. Closing it.
This is just ridiculous, I know React Navigation does not support this but how can that be so? This is a typical use case.
I tried to use popTo and it works okey expect that using autofocus on TextInputs makes the keyboard jump up and down since the scenes seems to mount and unmount when they are poped.
@aksonov is it possible to remove scenes from stack in the 3.0 version?
@qmegas Did you manage to get it to work?
Actions.popTo('sceneName') - scene may or may not be present and we can go to previous screen by swiping from left side to right side in phone. so we can't use this exactly. Is there any workaround for this?
popTo worked for me.
@qmegas Here's what you should do. Wrap screen3 and screen4 into a separate Router and put that Router inside a Modal scene. Like this:
<Router>
<Modal>
<Stack>
<Scene key="Scene1" component={Scene1} />
<Scene key="Scene2" component={Scene2} />
<Scene key="Scene5" component={Scene5} />
</Stack>
<Scene key="Scene3">
<Router>
<Scene key="Scene3Inner" component={Scene3} />
<Scene key="Scene4" component={Scene4} />
</Router>
</Scene>
</Modal>
</Router>
Then, when user gets to scene4, and about to go to scene5, you do this:
Actions.popTo('Scene2');
Actions.Scene5();
Your restricted scenes will open up in a modal, and they will have their own stack, so user can go back to Scene3 from Scene4, and can swipe down back to Scene2 from any scene in that new stack as well. But when user gets to Scene5, he can only swipe back to Scene2. Scene3 and Scene4 will be gone.