Skip to content

feat: [Question about the router] React router renders multiple routes  #28059

Closed as not planned

Description

@noskovvkirill

Prerequisites

Describe the Feature Request

I'm curious why the router for React is setup in the way it does. It renders multiple routes (presumably for transitions) in parallel and that leads to various issues (useEffect behaves differently and we have to useIonViewDidEnter/useIonViewDidLeave). It's hard for us to enable shared layout animations (because once we push the new route the old one still exists). We are also stuck with the old version of the React router and don't get the latest features. We would like to consider other router alternatives.

Wouldn't it make more sense to set up ionic in a way that doesn't depend on a specific router, and then add animations using something like Framer Motion Layout animations? (https://www.framer.com/motion/layout-animations). It seems like this approach could simplify things. What do you think?

Describe the Use Case

We're thinking about using a Next.js Router or TanStack router instead. Before we make the switch, we want to make sure we're not overlooking anything important.

Describe Preferred Solution

Transitions are independent of the Router.

Describe Alternatives

No response

Related Code

No response

Additional Information

No response

Activity

  1. self-assigned this
    on Aug 25, 2023
  2. liamdebeasi commented on Aug 25, 2023

    @liamdebeasi
    Contributor

    Hey there,

    So there's a few questions here:


    Why do views render multiple times/why do they stick around in the DOM?

    So one of the big differences between web apps and mobile apps is with state management. In a mobile app, previous views are typically persisted so users can go back to them. For example, imagine you had a long form on PageA. You entered your email and other information, changed the scroll position, and then pressed a button to go to PageB. Many users expect that when they return to PageA that the page will be exactly how they left it. This means that the scroll position should be preserved, the text they entered into the form should be preserved, etc.

    We could make developers responsible for persisting all of this information, but that seemed very cumbersome so we opted to preserve the state of the component in the DOM. Libraries such as React Navigation for React Native use a very similar technique.

    The other reason is for swipe to go back on iOS. While on PageB, users should be able to partially swipe back to reveal the contents of PageA. The swipe could happen at any time, so PageA needs to be ready to be shown at any time.

    Why is Ionic still using React Router 5?

    The primary issue here is due to the number of breaking changes in React Router 6. Not only were there changes to the library itself, but the type definitions changed considerably since React Router 6 ships its own types instead of relying on DefinitelyTyped. Additionally, an underlying package called history received many breaking changes too.

    We know this is not an ideal scenario, so we are working on some router improvements that will a) allow us to support React Router 5 and 6 and b) make it easier to add support for newer versions of React Router (and potentially support other routers).

    You can track support for this in #24177.

    Why do we add our own custom logic coupled to JS Framework routers instead of writing our own/using a general purpose router?

    The short answer is the navigation component of most JS routers are not suitable for mobile applications. Evan You, creator of Vue, summarized this problem fairly well here: vuejs/vue-router#2052 (comment)

    There are two components to our routing support:

    1. Navigation: This is this visual representation of your router state. It controls rendering State A and State B, as well as the transition between State A and State B (and vice versa). One of the fundamental differences between web apps and mobile apps is that mobile apps use stack-based navigation. Apps can have multiple independent stacks (think of tabs where each tab is its own stack). The navigation provided by JS routers does not support this use case, so Ionic has to build their own custom logic here. This results in the custom ion-router-outlet component.

    2. Routing: This is the mapping of a URL to a component. For example, the router handles mapping URL /foo to component Foo. We actually did write a custom router in the past (see ion-router), but the feedback from the JS Framework community was fairly negative. Developers want to use tooling that is familiar to them. So Angular devs want to use Angular Router, Vue devs want to use Vue Router, etc. We felt that building our own router or relying on some general purpose router would make it harder for developers to adopt Ionic.

    Can I use an unsupported router with Ionic?

    Yes, though you lose many of the navigation features that make an app feel native. Page transitions, state management, native tabs (note that most tabs libraries are focused on web apps and do not implement native mobile tabs correctly), swipe to go back, etc are all things that you lose out on by opting not to use Ionic's routing integration. You are able to build some of the integrations yourself, but they are typically very challenging to get right (especially tabs).


    Hopefully this answered most of your questions, but let me know if you have any more!

  3. removed their assignment
    on Aug 25, 2023
  4. noskovvkirill commented on Aug 25, 2023

    @noskovvkirill
    Author

    Thanks @liamdebeasi for a very generous explanation. It answers all our questions. I think specifically the point of state preservation is interesting and makes sense from UX

  5. ionitron-bot commented on Oct 1, 2023

    @ionitron-bot

    Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

  6. locked and limited conversation to collaborators on Oct 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions