Skip to content

Differences in Server-Driven Routing #175

@leonvogt

Description

@leonvogt

Hi there,

We have noticed some differences in behavior between iOS and Android when performing server side routing actions (recede, refresh, resume) from within a modal.
Similar / Related issues: #84, #153

To get an overview of the current situation I've tried to create the tables below.

TL;DR:

  • Android reloads the URL of the modal in the case of a "refresh". Which in some cases can even trigger a race condition where the content of the modal will get shown in fragment of the main stack.
  • Android loses the updated URL after refresh or resume. iOS respects the updated / current WebURL.
  • Android does reload a fragment after a "resume", compared to iOS which does not.

1. Modal -> Direct link to server side routing URLs

Android iOS Identical?
recede 1. Close modal
2. Pop to screenA
3. No refresh on screenA
1. Close modal
2. Pop to screenA
3. No refresh on screenA
recede (with JS URL update) 1. Close modal
2. Pop to screenA
3. No refresh on screenA
1. Close modal
2. Pop to screenA
3. No refresh on screenA
refresh 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB
refresh (with JS URL update) 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB, and loses updated URL from JS

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB WITH updated URL with JS
resume 1. Close modal 1. Close modal
resume (with JS URL update) 1. Close modal 1. Close modal

2. Modal -> Form Submit -> Server side redirect

Android iOS Identical?
recede 1. Close modal
2. Pop to screenA
3. Refresh screenA
1. Close modal
2. Pop to screenA
3. Refresh screenA
recede (with JS URL update) 1. Close modal
2. Pop to screenA
3. Refresh screenA
1. Close modal
2. Pop to screenA
3. Refresh screenA
refresh 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB
refresh (with JS URL update) 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB, and loses updated URL from JS
1. Close modal
2. Refresh screenB WITH updated URL with JS
resume 1. Close modal
2. Refresh screenB
1. Close modal
resume (with JS URL update) 1. Close modal
2. Refresh screenB, and loses updated URL from JS
1. Close modal

Test Setup:

  • Navigation stack: screenA → screenB
  • Modal opened from screenB
  • Tested with iOS: v1.2.2 / Android: v1.2.4
  • Tested with the demo app and this fork of the demo server. All relevant changes were done in this commit

Reproduction Steps:

  • Open the demo app
  • Navigate with "Basic navigation" link
  • (For JS URL update scenarios) Click "SET param foo" button
  • Navigate with "Modal navigation" link
  • Trigger one of the server-side routing paths

Screen recording of an example test run: (Server side redirect /refresh_historical_location (with JS URL update))
https://github.com/user-attachments/assets/da11a70f-d877-43c0-9ac6-012cd3d92a15

Main questions

  1. Android loses the updated URL after refresh or resume. iOS respects the updated / current WebURL.
  2. Android reloads the URL of the modal in the case of a "refresh". Which in some cases can even trigger a race condition where the content of the modal will get shown in fragment of the main stack.
  3. Android does reload screen 1 after a "resume" redirection of the server. Even though it should not reload anything.

Background:

  • In Hotwire Native Android we check the upcoming URL against the startingLocation. When you update the URL with JS, the startingLocation remains the same. Which explains why the updated URL is lost on refresh / resume.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions