Skip to content

fix(form-data): prevent input delays after navigating large forms - #4348

Merged
olemartinorg merged 2 commits into
mainfrom
codex/cache-form-data-selector-paths
Sep 30, 2026
Merged

olemartinorg merged 2 commits into
mainfrom
codex/cache-form-data-selector-paths

Conversation

@olemartinorg

@olemartinorg olemartinorg commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

Typing in a large form became slower after visiting more pages. Form-data selectors cached each newly created binding object by identity, even when it named a field already in the cache. Each edit then reevaluated all prior copies.

Cache form-data selections by data type and field. The Zustand context helpers now pass a custom cache key to delayed selectors. Repeated references to the same field share one cached selection, and store changes still update the value.

In RA-0846-01, typing 44 characters on “Kommentarar og merkader” after each full form tour took 2.46, 4.79, and 7.23 seconds before this change. It took 0.40, 0.30, and 0.39 seconds afterward. Retained heap after the three tours fell from 93 MiB to 52 MiB.

Related Issue(s)

Verification/QA

  • Manual functionality testing
    • I have tested these changes manually
    • Creator of the original issue (or service owner) has been contacted for manual testing (or will be contacted when released in alpha)
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added/updated
    • Cypress E2E test(s) have been added/updated
    • No automatic tests are needed here (no functional changes/additions)
    • I want someone to help me make some tests
  • UU/WCAG
    • I have tested with a screen reader/keyboard navigation/automated wcag validator
    • No testing done/necessary (no DOM/visual changes)
    • I want someone to help me perform accessibility testing
  • User documentation @ altinn-studio-docs
    • Has been added/updated
    • No functionality has been changed/added, so no documentation is needed
    • I will do that later/have created an issue
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board
    • I don't have permissions to do that, please help me out
  • Labels
    • I have added a kind/* and backport* label to this PR for proper release notes grouping
    • I don't have permissions to add labels, please help me out

Summary by CodeRabbit

  • Bug Fixes
    • Improved refresh behavior for delayed form data selections when equivalent object arguments are used. Unchanged selections no longer trigger unnecessary recalculations during re-renders, while updates to the underlying data continue to appear in displayed values.
    • Updated form data selection behavior to distinguish fields and data types, helping ensure that changes are reflected in the appropriate selections.

Ole Martin Handeland added 2 commits September 29, 2026 21:00
Repeated render paths create new binding objects for the same data type and field. The identity-based default key retained every object and made each later edit reevaluate all prior bindings.

Pass a stable path key through the Zustand context helpers and use it for form-data delayed selectors. In RA-0846-01, a 44-character input stayed below 0.4 seconds after three full form tours, while the prior build rose to 6.9 seconds.
Exercise direct and lax delayed selectors with fresh objects for the same binding. Repeated renders must reuse the cached selection, while a store change must still update the displayed value.
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: bdd99807-8187-4342-ba27-254b562d0eb5

📥 Commits

Reviewing files that changed from the base of the PR and between 19cb5d4 and 71409e3.

📒 Files selected for processing (3)
  • src/core/contexts/zustandContext.tsx
  • src/features/formData/FormDataWrite.tsx
  • src/hooks/delayedSelectors.test.tsx

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Delayed-selector hooks now accept optional cache-key functions. Form-data selectors pass a key derived from each data-model reference. A regression test checks selector behavior with object arguments across re-renders and store updates.

Changes

Delayed selector cache keys

Layer / File(s) Summary
Custom cache-key API and regression test
src/core/contexts/zustandContext.tsx, src/hooks/delayedSelectors.test.tsx
Zustand context hooks forward an optional cache-key function. The test checks that equivalent object arguments do not rerun selectors across re-renders and that store updates refresh displayed values.
Form-data selector cache keys
src/features/formData/FormDataWrite.tsx
Form-data selector hooks pass a key function that returns the reference’s dataType and field.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 71409

No actionable issue remains from this review; the change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 71409

The reviewed form selectors still read the same fields from their existing store. No security boundary change or security finding was established, although the available integration evidence does not cover every caller.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — For the inspected path, cache reuse is limited to a hook controller and its selected store; the change does not establish a new cross-store cache. Runtime tenant boundaries were not available to assess.

Trust Boundaries and Controls

  • inferred — Reference fields determine the selected form-data path both before and after cache reuse. The inspected code shows no additional data source or bypass of the existing missing-context check.

Resilience and Maintainability Implications

  • observed — Changed selected values trigger cache invalidation and a fresh selector function, limiting stale reuse after observed store updates.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly describes the main change: preventing input delays in large forms.
Description check ✅ Passed The description explains the problem, solution, measured performance impact, related context, and verification results. It includes the required sections and records unit-test and accessibility decisi…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@olemartinorg olemartinorg added kind/bug Something isn't working backport This PR should be cherry-picked onto older release branches labels Sep 29, 2026
@olemartinorg

Copy link
Copy Markdown
Contributor Author

/publish

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

PR release:

  • <link rel="stylesheet" type="text/css" href="https://altinncdn.no/toolkits/altinn-app-frontend/4.33.0-pr.5860.cache-form-data-selector-paths.71409e3f/altinn-app-frontend.css">
  • <script src="https://altinncdn.no/toolkits/altinn-app-frontend/4.33.0-pr.5860.cache-form-data-selector-paths.71409e3f/altinn-app-frontend.js"></script>

⚙️ Building...
✅ Done!

@JamalAlabdullah JamalAlabdullah left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@olemartinorg
olemartinorg merged commit 62b69b2 into main Sep 30, 2026
15 of 16 checks passed
@olemartinorg
olemartinorg deleted the codex/cache-form-data-selector-paths branch September 30, 2026 09:46
@github-actions

Copy link
Copy Markdown
Contributor

✅ Automatic backport successful!

A backport PR has been automatically created for the release/v4.33 release branch.

The release branch release/v4.33 already existed and was updated.

The cherry-pick was clean with no conflicts. Please review the backport PR when it appears.

olemartinorg added a commit that referenced this pull request Sep 30, 2026
)

* fix(form-data): bound selector caches by data model path

Repeated render paths create new binding objects for the same data type and field. The identity-based default key retained every object and made each later edit reevaluate all prior bindings.

Pass a stable path key through the Zustand context helpers and use it for form-data delayed selectors. In RA-0846-01, a 44-character input stayed below 0.4 seconds after three full form tours, while the prior build rose to 6.9 seconds.

* test(form-data): cover equivalent binding selector keys

Exercise direct and lax delayed selectors with fresh objects for the same binding. Repeated renders must reuse the cached selection, while a store change must still update the displayed value.

---------

Co-authored-by: Ole Martin Handeland <git@olemartin.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR should be cherry-picked onto older release branches kind/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants