Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove scenes from stack #2713

Closed
qmegas opened this issue Dec 18, 2017 · 16 comments
Closed

Remove scenes from stack #2713

qmegas opened this issue Dec 18, 2017 · 16 comments
Labels

Comments

@qmegas
Copy link

qmegas commented Dec 18, 2017

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?

@Blapi
Copy link
Collaborator

Blapi commented Dec 18, 2017

What about Actions.popTo('screen2') when the user leaves the screen5 ? Seems easier

@qmegas
Copy link
Author

qmegas commented Dec 18, 2017

@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.

@Blapi
Copy link
Collaborator

Blapi commented Dec 18, 2017

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.

@Blapi
Copy link
Collaborator

Blapi commented Dec 18, 2017

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.

@qmegas
Copy link
Author

qmegas commented Dec 19, 2017

@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?

@Blapi
Copy link
Collaborator

Blapi commented Dec 19, 2017

I don't know, I haven't checked

@qmegas
Copy link
Author

qmegas commented Dec 20, 2017

@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.

@Blapi
Copy link
Collaborator

Blapi commented Dec 21, 2017

What's the status now?

@qmegas
Copy link
Author

qmegas commented Dec 21, 2017

@Blapi now?

@Blapi
Copy link
Collaborator

Blapi commented Dec 21, 2017

Yes, is it working well? Did you find a workaround?

@qmegas
Copy link
Author

qmegas commented Dec 22, 2017

@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.

@aksonov aksonov added the wontfix label Jan 4, 2018
@aksonov
Copy link
Owner

aksonov commented Jan 4, 2018

Unfortunately it is how react navigation works. Closing it.

@aksonov aksonov closed this as completed Jan 4, 2018
@andidev
Copy link

andidev commented Feb 18, 2018

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?

@Balasnest
Copy link

@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?

@Samesh
Copy link

Samesh commented Apr 11, 2020

popTo worked for me.

@pistonsky
Copy link

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants