Skip to content

update for 5.5.0-beta-1#48

Merged
MangelMaxime merged 3 commits into
elmish:masterfrom
et1975:master
Mar 3, 2026
Merged

update for 5.5.0-beta-1#48
MangelMaxime merged 3 commits into
elmish:masterfrom
et1975:master

Conversation

@et1975

@et1975 et1975 commented Mar 2, 2026

Copy link
Copy Markdown
Member

Update Fable.Elmish.React to 5.5.0-beta-1

Package update (via dotnet paket update)

  • paket.lockFable.Elmish.React updated from 5.0 to 5.5.0-beta-1
  • paket.dependencies — already had >= 5 prerelease which resolves to the new version

Source code — src/common.fs

  • Removed the class-component approach (Component<LazyProps,LazyState> with shouldComponentUpdate) — v5.5 replaced this with React.memo
  • Removed open Elmish.React.Internal (no longer needed; old package didn't have this module, new one has it but only for updateInputValue)
  • Removed LazyProps, LazyState, and Components.LazyView types
  • Rewrote all lazyView* functions using React.memo with emitJsExpr/emitJsStatement (matching the upstream pattern)
  • HMR awareness is now achieved by including hmrCount in memo props — when window.Elmish_HMR_Count changes, the comparison returns false and forces a re-render
  • lazyView2With and lazyView3With now take 2 args and return a function (matching v5.5's calling convention used by withReactBatchedUsing etc.)
  • #else (release) branches updated to match new upstream signatures

New unit tests (14 added, 33 total)

withKey tests (8 tests in LazyViewTests.fs) — ported from the elmish/react repo, exercising withKey through HMR's memo wrappers:

Test What it verifies
sets key on a lazyView2 element withKey "my-key" on a lazyView2With element sets .key
sets key on a lazyViewWith element Same for 1-arg lazyViewWith
sets key on a lazyView3 element Same for 3-arg lazyView3With
sets key on a plain ReactElement withKey works on non-memo elements too
element without withKey has no key Baseline: .key is None without withKey
preserves element type withKey doesn't change the component type (no remount)
memo still skips render with withKey Keyed memo element still skips re-render when model is unchanged
keyed elements are reordered without remount 3 keyed children reordered from [A,B,C]→[C,A,B]; mount count stays at 3 (React reconciles by key, no remounts)

Root caching tests (6 tests in ProgramTests.fs) — verify the HMR fix that caches React roots across hot reloads:

Test What it verifies
returns same root for same placeholderId RootCache.getOrCreateRoot returns the same IReactRoot instance on repeated calls
returns different roots for different placeholderIds Different placeholder IDs get independent roots
component is not remounted when model changes via cached root Tracked component (via useEffect mount counter) proves mount count stays at 1 across 3 model changes
simulating HMR reload: reusing cached root does not remount New lazyView2With partial application + cached root = same root instance, no remount
withReactSynchronous does not remount on multiple setState calls Synchronous rendering path also keeps mount count at 1
savePendingRaf and cancelPendingRaf round-trip RAF handle is stored and cleared correctly

@MangelMaxime

Copy link
Copy Markdown
Member

The code is looking good to me, and I tested it locally and it is working.

I just have one question which I asked in the original PR.

@et1975

et1975 commented Mar 2, 2026

Copy link
Copy Markdown
Member Author

Added root caching and related unit-tests.

@MangelMaxime
MangelMaxime merged commit 0303fa3 into elmish:master Mar 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants