Skip to content

Navigation history isn't updated correctly in preexistingReportID handling #28572

Description

@roryabraham

HOLD on #27996

Problem

We have a bit of code here to re-route the user if they are looking at an optimistically-generated reportID. However, it only works if that report is the active route, and doesn't work in a number of different situations. For example:

Actions taken

  1. Sign in as a new user, Alice
  2. Sign in as an existing user, Bob
  3. As Alice, go to Settings -> Preferences and toggle Force Offline.
  4. As Alice, send a few messages in a new chat to Bob (offline)
  5. As Bob (online), send a message to Alice
  6. As Alice, go to Settings -> Preferences and untoggle Force Offline.

Expected behavior

In the background, the report should rerender to the correct report, showing the messages from Alice and Bob. If you then close the Settings modal/RHP, then you should see the new report, not the unused optimistic one.


I'm quite certain there are other edge cases that won't work correctly, like pressing the browser back button a few times to return to the unused optimistic report.

Actual behavior

You'll see the 404 page.

Solution

At a high level, the solution should be to re-write the navigation state and history to replace all instances of the unused reportID with the correct one.

I started working on a solution to this in #27996, but decided to drop it and treat it as a separate issue.

The solution I'm most confident in leverages a function added in #27996, and looks like this:

diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js
index dc4f35a59c..569ffaf7d4 100644
--- a/src/libs/Navigation/Navigation.js
+++ b/src/libs/Navigation/Navigation.js
@@ -13,6 +13,7 @@ import originalGetTopmostReportId from './getTopmostReportId';
 import getStateFromPath from './getStateFromPath';
 import SCREENS from '../../SCREENS';
 import CONST from '../../CONST';
+import deepReplaceKeysAndValues from '../deepReplaceKeysAndValues';
 
 let resolveNavigationIsReadyPromise;
 const navigationIsReadyPromise = new Promise((resolve) => {
@@ -255,6 +256,17 @@ function setIsNavigationReady() {
     resolveNavigationIsReadyPromise();
 }
 
+/**
+ * Replace a given reportID in the navigation stack.
+ *
+ * @param {String} oldReportID
+ * @param {String} newReportID
+ */
+function replaceReportIDInNavigationStack(oldReportID, newReportID) {
+    const updatedState = deepReplaceKeysAndValues(navigationRef.getRootState(), oldReportID, newReportID);
+    navigationRef.resetRoot(updatedState);
+}
+
 export default {
     setShouldPopAllStateOnUP,
     canNavigate,
@@ -268,6 +280,7 @@ export default {
     setIsNavigationReady,
     getTopmostReportId,
     getRouteNameFromStateEvent,
+    replaceReportIDInNavigationStack,
 };
 
 export {navigationRef};
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 66008ae5ae..28f3dbed14 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -969,11 +969,7 @@ function handleReportChanged(report) {
     if (report && report.reportID && report.preexistingReportID) {
         Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, null);
 
-        // Only re-route them if they are still looking at the optimistically created report
-        if (Navigation.getActiveRoute().includes(`/r/${report.reportID}`)) {
-            // Pass 'FORCED_UP' type to replace new report on second login with proper one in the Navigation
-            Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.preexistingReportID), CONST.NAVIGATION.TYPE.FORCED_UP);
-        }
+        Navigation.replaceReportIDInNavigationStack(report.reportID, report.preexistingReportID);
         return;
     }
 

I also put a good amount of work into writing automated UI tests to cover these kind of esoteric navigation changes. Those tests were definitely imperfect, but you can see them deleted in this commit and it's hopefully a good starting point.

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~015e5d9751f42a757a
  • Upwork Job ID: 1718973704710303744
  • Last Price Increase: 2023-10-30
Issue OwnerCurrent Issue Owner: @roryabraham

Activity

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

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.EngineeringInternalRequires API changes or must be handled by Expensify staffWeeklyKSv2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions