You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Android - Expense - Report field value jumps when navigating from one report to another #101798
Version Number: 9.4.91-0 Reproducible in staging?: Yes Reproducible in production?: No If this was caught during regression testing, add the test name, ID and link from BrowserStack: github.com//pull/100735 Email or phone of affected tester (no customers):sjodjoijsonjoinj@gmail.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Samsung Galaxy S25 FE / Android 16 App Component: Money Requests
Action Performed:
Precondition:
Create text and list type report field.
Launch Expensify app.
Go to workspace chat.
Create two reports with two expenses each. Add anything to text report field.
Go to Spend > Reports.
Open any report.
Tap next arrow button.
Expected Result:
Report field value will not jump when navigating from one report to another.
Actual Result:
Report field value jumps when navigating from one report to another.
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
The regression is a visual one in brand-new UI, and the fix is a two-line prop change (pin the floating label with forceActiveLabel) versus reverting a ~1,100-line feature that three later PRs have already merged around. Reverting is the fallback if the targeted fix does not hold up in testing.
Assigned: @Gonals, @daledah (approving reviewers of the causing PR) — already assigned by Melvin, plus the PR author Labels: No label changes. DeployBlockerCash stays (an App PR caused this); DeployBlocker was never applied, so nothing to remove.
📋 Detailed Analysis
Evidence
Applause's pointer at #100735 is confirmed, not refuted. That PR replaced the report field rows in the report view (previously static MenuItemWithTopDescription rows) with live, editable inputs: ReportFieldInlineInput.tsx is a new file added by it, and MoneyRequestViewReportFields.tsx was rewritten into a grid of those inputs.
It is the only PR in the 9.4.91-0 checklist that touches report field rendering. Filtering the release range for changes to the report field UI leaves three PRs, and the other two are unrelated refactors:
Matches "reproducible on staging, not production": ReportFieldInlineInput.tsx does not exist on the production branch at all, so the inline-input UI ships for the first time in this release.
The repro's precondition is a text field and a list field — precisely the two branches of the new component that render a bare TextInput. The date branch goes through DatePicker, which already pins its label with forceActiveLabel, and is therefore immune to the animation described below.
Verification
Affected files (all modified or added by #100735):
Tapping the next arrow does not remount the report screen — it calls Navigation.setParams({reportID}), so the report field inputs keep their React identity (their keys are built from fieldKey only, which is the same for every report in the workspace) and simply receive the next report's values as new props.
The next report's field values do not arrive in the same frame as the reportID change: the fields are built from getReportFieldMaps(report, policy.fieldList, …), so until that report's own fieldList is hydrated (OpenReport) the value resolves to the policy default, which is usually empty. The mounted inputs therefore see the value sequence "Report A value" → "" → "Report B value".
Before #100735 that sequence was invisible: a MenuItemWithTopDescription keeps its description pinned at the top and just swaps the title text. Now the value lives inside a floating-label TextInput. Every empty ⇄ non-empty flip runs the 200 ms label animation, so the label drops to the middle of the field and rises again while the value text pops in behind it — the "jump" in the video. The date field is unaffected because DatePicker passes forceActiveLabel; the text and list fields (exactly the two in the repro) do not.
The same reuse also carries validationError / hasBeenBlurred state from one report into the next, which is a second, smaller symptom of the same "inputs are never remounted per report" issue.
Suggested fix (targeted)
Pass forceActiveLabel to both TextInputs in ReportFieldInlineInput (the list-field button input at L203-L220 and the text/formula input at L227-L243), matching what the date branch already gets from DatePicker. The label is then pinned in its raised position and the value renders in its final spot no matter when the data lands — no animation, no jump.
Optional hygiene, same PR: include the report ID in the field key in MoneyRequestViewReportFields (key on report ID plus fieldKey, instead of fieldKey alone) so each report gets fresh inputs and no draft or validation state leaks across the next/prev arrows.
Please re-test the repro on Android after step 1 — if the jump persists, revert #100735 for this release.
Activity
applause-bot commentedon Sep 21, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/fe54a1a54e38ec288ff234438b60c842e5a1d140fe68fb71dce3e2c9962f3e39
melvin-bot commentedon Sep 21, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #100735
melvin-bot commentedon Sep 21, 2026
@Gonals @daledah you have been assigned to this deploy blocker because you reviewed the offending PR: #100735
github-actions commentedon Sep 21, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
melvin-bot commentedon Sep 21, 2026
💬 A slack conversation has been started in #expensify-open-source
MelvinBot commentedon Sep 21, 2026
🔍 Investigation Summary
Classification: Frontend bug
Causing PR: Show up to three report fields per row and edit them inline (
Expensify/App#100735) by @MelvinBot (High confidence that this PR caused it; Medium-High confidence on the exact mechanism below)Related Issues: none found
Recommendation: ROLL FORWARD
The regression is a visual one in brand-new UI, and the fix is a two-line prop change (pin the floating label with
forceActiveLabel) versus reverting a ~1,100-line feature that three later PRs have already merged around. Reverting is the fallback if the targeted fix does not hold up in testing.Assigned: @Gonals, @daledah (approving reviewers of the causing PR) — already assigned by Melvin, plus the PR author
Labels: No label changes.
DeployBlockerCashstays (an App PR caused this);DeployBlockerwas never applied, so nothing to remove.📋 Detailed Analysis
Evidence
MenuItemWithTopDescriptionrows) with live, editable inputs:ReportFieldInlineInput.tsxis a new file added by it, andMoneyRequestViewReportFields.tsxwas rewritten into a grid of those inputs.git log origin/production..origin/staging -- src/components/MoneyRequestReportView src/components/ReportActionItem/MoneyReportView.tsx src/pages/EditReportFieldDropdown.tsx src/hooks/useSaveReportField.ts→ Show up to three report fields per row and edit them inline #100735, refactor: extract useMoneyRequestReportColumns and useMoneyRequestReportLayout (transaction table columns only) and [No QA] Fix import/no-cycle - part 12 (import-cycle cleanup only).ReportFieldInlineInput.tsxdoes not exist on theproductionbranch at all, so the inline-input UI ships for the first time in this release.TextInput. The date branch goes throughDatePicker, which already pins its label withforceActiveLabel, and is therefore immune to the animation described below.Verification
Affected files (all modified or added by #100735):
src/components/MoneyRequestReportView/ReportFieldInlineInput.tsx#L203-L220— list field input, noforceActiveLabelsrc/components/MoneyRequestReportView/ReportFieldInlineInput.tsx#L227-L243— text/formula field input, noforceActiveLabelsrc/components/MoneyRequestReportView/ReportFieldInlineInput.tsx#L73-L81— render-phase state sync that re-seeds the draft when the saved value changessrc/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx#L74-L95— each field is keyed only by itsfieldKey, so the key is identical across reports of the same workspaceSupporting (unchanged) code that makes the above visible:
src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx#L186-L200— the next/prev arrows navigate withNavigation.setParams({reportID}), i.e. the screen and its whole subtree stay mounted; only thereportIDparam changes.src/components/TextInput/BaseTextInput/implementation/index.native.tsx#L116and#L224-L236— the floating label starts active only if the value is non-empty at mount, and otherwise animates between the centered and raised positions with a 200 mswithTimingwhenever the value flips empty ⇄ non-empty.Root Cause
Tapping the next arrow does not remount the report screen — it calls
Navigation.setParams({reportID}), so the report field inputs keep their React identity (their keys are built fromfieldKeyonly, which is the same for every report in the workspace) and simply receive the next report's values as new props.The next report's field values do not arrive in the same frame as the
reportIDchange: the fields are built fromgetReportFieldMaps(report, policy.fieldList, …), so until that report's ownfieldListis hydrated (OpenReport) the value resolves to the policy default, which is usually empty. The mounted inputs therefore see the value sequence "Report A value" → "" → "Report B value".Before #100735 that sequence was invisible: a
MenuItemWithTopDescriptionkeeps its description pinned at the top and just swaps the title text. Now the value lives inside a floating-labelTextInput. Every empty ⇄ non-empty flip runs the 200 ms label animation, so the label drops to the middle of the field and rises again while the value text pops in behind it — the "jump" in the video. The date field is unaffected becauseDatePickerpassesforceActiveLabel; the text and list fields (exactly the two in the repro) do not.The same reuse also carries
validationError/hasBeenBlurredstate from one report into the next, which is a second, smaller symptom of the same "inputs are never remounted per report" issue.Suggested fix (targeted)
forceActiveLabelto bothTextInputs inReportFieldInlineInput(the list-field button input at L203-L220 and the text/formula input at L227-L243), matching what the date branch already gets fromDatePicker. The label is then pinned in its raised position and the value renders in its final spot no matter when the data lands — no animation, no jump.MoneyRequestViewReportFields(key on report ID plusfieldKey, instead offieldKeyalone) so each report gets fresh inputs and no draft or validation state leaks across the next/prev arrows.Please re-test the repro on Android after step 1 — if the jump persists, revert #100735 for this release.
melvin-bot commentedon Sep 21, 2026
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.
If a regression has occurred and you are the assigned CM follow the instructions here.
If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.
melvin-bot commentedon Sep 21, 2026
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.
If a regression has occurred and you are the assigned CM follow the instructions here.
If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.
melvin-bot commentedon Sep 21, 2026
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.
If a regression has occurred and you are the assigned CM follow the instructions here.
If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.
Gonals commentedon Sep 22, 2026
PR reverted
IuliiaHerets commentedon Sep 22, 2026
Xiaomi Redmi Note 10 / Android 12
9.4.91-1
Passed
Screenrecorder-2026-09-22-14-24-39-65.mp4