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

Fix TabsRoute behaviour #17

Open
jonathanglasmeyer opened this issue Jun 12, 2016 · 6 comments
Open

Fix TabsRoute behaviour #17

jonathanglasmeyer opened this issue Jun 12, 2016 · 6 comments
Assignees

Comments

@jonathanglasmeyer
Copy link
Collaborator

TabsRoute should implement two behaviours:

  • it should save the state for each child route and restore it when switching tabs
  • it should reset a child's state if that child is being navigated to twice

Given the following route config:

<Router>
  <TabsRoute path="/" ...>
    <StackRoute path="/foo" ...>
      <Route path="a" ... />
      <Route path="b" ... />
    </StackRoute>
    <Route path="/bar" .../>
  </TabsRoute>
</Router>

Visiting routes should lead to the following results respectively:

  1. /foo --> show /foo
  2. /foo/a --> show /foo/a
  3. /foo/b --> show /foo/b
  4. /bar --> show /bar
  5. /foo --> show /foo/b (a tab route saves and restores its children's state)
  6. /foo --> should reset stack of the child stack route and show /foo
@jmurzy
Copy link
Owner

jmurzy commented Jun 12, 2016

it should save the state for each child route and restore it when switching tabs

This is supported when root route, /, is leaf of a TabsRoute. I'll make the necessary changes to cover most other cases as well. It's the <StackRoute> that's causing <TabsRoute> to misbehave. It gets a bit tricky when we have nested routes. Making the default reducer used by <StackRoute> route order aware should fix this.

it should reset a child's state if that child is being navigated to twice

This is in the README under Advanced Usage. It is possible with a custom route reducer. But we should probably make this the default behavior.

🍺

@joonhocho
Copy link

Can the state also include its scroll position?
Native apps seem to store everything including scroll position, or maybe they keep the rendered view alive somewhere and simply switch to it.
I wonder how the life cycle works for those tabs in the native apps.

@jonathanglasmeyer
Copy link
Collaborator Author

The F8 app does this, uses NavExp and is open source. So it should be possible. Haven't investigated this in detail but it's a must-have for sure.

@jmurzy
Copy link
Owner

jmurzy commented Jun 13, 2016

@jonathanewerner @joonhocho That is supported. Previously, there was a bug in NavigationExperimental that dropped component state when swtiching tabs. But that's now fixed, and <Route> and its siblings should now retain component state on all navigation state updates. This includes <ScrollView> state e.g. scroll position, animation state.

UINavigationContoller extends UIViewController and uses the good old lifecycles inherited from it. It does retain all UIViewController instances that are then pushed to it. Very similar to how we do it. Both <TabsRoute> and <StackRoute> retain references to your previously focused views. Here's how they would look when you inspect the view hierarchy.

<StackRoute> with 3 active views
      +------------+
    +-+            |
  +-+ |            |
  | | |            |
  | | |  Focused   |
  | | |   View     |
  | | |            |
  +-+ |            |
    +-+            |
      +------------+

Here a <Pop> would drop the focused view revealing the previous view in the stack with a transition animation. The views in a stack are never unmounted during a transition so you keep your component state. Transition animations can also be customized using transitionRegistry.

<TabsRoute> with 3 active views
 * +-------------+-------------+-------------+
 * |             |             |             |
 * |             |             |             |
 * |             |             |             |
 * |    Next     |   Focused   |  Previous   |
 * |    View     |    View     |    View     |
 * |             |             |             |
 * |             |             |             |
 * |             |             |             |
 * +-------------+-------------+-------------+

By default, transition animations are turned off for <TabsRoute> mirroring native behavior. But there's nothing preventing you from making them animate when switching tabs. Aviato example does this for its inner "swticher" tabs.

<TabsRoute> is also smart enough to lazily render its tabs. So when your app launches, you will have only one of the tabs (focused view) rendered, but once you tap other tabs, all are retained until you kill the app.

Are you perhaps running into a bug we can try to reproduce and fix?

🍺

@joonhocho
Copy link

Thanks @jmurzy for such detailed answer.
I once noticed that tabs on react native apps did not retain previous view states, but did not know that it was fixed.
It's pretty cool to know how they can lazily render other tabs.

@aforty
Copy link

aforty commented Oct 17, 2016

Any movement on this? This is quite limiting and is stopping me from truly being able to use this on my app. Switching between tabs does not retain that tabs state and instead pushed the new route on top. I also don't know enough to write my own reducer, that seems that's pretty involved.

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

No branches or pull requests

4 participants