Skip to content

Unexpected behaviour with clear_all and replace_root #107

@leonvogt

Description

@leonvogt

I've experienced some unexpected behavior where clear_all and replace_root lead to more requests than expected.

Related Issues on the Android side: hotwired/hotwire-native-android#115

Replace root

Steps to reproduce:

  1. Ensure the Demo app has the following path configuration snippet (should be included by default):
{
  "patterns": [
     "^/$"
  ],
  "properties": {
     "presentation": "replace_root"
  }
},
  1. Update the server.js file of the Demo Server like this:
app.get("/two", (request, response) => {
-  response.render("two", { title: "Push or Replace?", action: request.query.action })
+  response.redirect("/")
})
  1. Navigate to /one (title: "Navigate to another page")
  2. Navigate to /two (title: "Advance to another webpage")

Expected Server Logs:

GET /one
GET /two
GET /

Actual Server Logs:

GET /one
GET /two
GET /
GET /
GET /

The routing documentation states, replace_root will:

Dismiss if modal screen then
Pop to root then
Replace root screen on main stack

The root screen route is loaded three times. With the exact same setup, Hotwire Native Android calls / twice.
My expectation was that the root screen would only be loaded once.

Clear all

There are two things I don't quite understand regarding clear_all. Here are the steps I followed to replicate the issue:
(Do not use the server code from the previous example)

  1. Add the following to the path configuration to use /two as a clear_all route:
{
  "patterns": [
    "^/two$"
  ],
  "properties": {
    "presentation": "clear_all"
  }
},
  1. Navigate to /one
  2. Navigate to /two

Expected Server Logs:

GET /one
GET /two
GET /

Actual Server Logs:

GET /one
GET /two

According to the documentation, clear_all will:

Dismiss if modal screen then
Pop to root then
Refresh root screen on main stack

Maybe I misunderstood what "refresh the root screen" means. I assumed it meant that after popping all screens, the app would load the root screen again.
Again, this might be intended behavior, but I wanted to mention it here for clarification.

Redirecting to a clear_all route

  1. Like before, add the following to the path configuration, to use /two as a clear_all route:
{
  "patterns": [
    "^/two$"
  ],
  "properties": {
    "presentation": "clear_all"
  }
},
  1. Update the server.js to redirect to /two:
app.get("/one", (request, response) => {
-  response.render("one", { title: "How’d You Get Here?" })
+  response.redirect("/two")
})
  1. Navigate to /one

Expected Server Logs:

GET /one
GET /two
GET /

Actual Server Logs:

GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two
GET /one
GET /two

I'm not sure why this is happening. Is it possible that clear_all isn't intended to be used with redirects?
My guess is that clear_all is only meant for a dedicated route to which we explicitly navigate, rather than redirecting to it.
I wanted to mention this here in case it's not the intended behavior.

To break it down:

  1. 3 requests to the root screen when using replace_root
  2. No request to the root screen when using clear_all
  3. Loop when redirecting to a clear_all route

I'm happy to help figure this out if you could clarify which behavior is intended and which is not.
Thanks!


Edit: I've tested it with v1.2.0 and could reproduce the same behaviour.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions