fixes root mounting and optimizes view functions#114
Conversation
| "react": "^17.0.2", | ||
| "react-dom": "^17.0.2", | ||
| "react": "^18.0.0", | ||
| "react-dom": "^18.0.0", |
There was a problem hiding this comment.
Any reason for not using 19?
There was a problem hiding this comment.
not really, conversely there doesn't appear to be such a drastic difference between 18 and 19 as between 17 and 18 (fibers) wrt to changes I'm making here. As this is a dev-only dependency, it shouldn't matter to consumers.
There was a problem hiding this comment.
I think we'll need to release react 19 support with a major version bump since it ditches root.render(). There also seem to be no need for memo...
There was a problem hiding this comment.
React 19 support has already been added;) root.render is the new API added in 18.
There was a problem hiding this comment.
Ohh, you're right... I remember you did that a year ago. I wonder why we didn't update devDependencies back then. Maybe @MangelMaxime needs it for that version of nacara?
There was a problem hiding this comment.
Nacara do use React indeed, but I should be able to update its React version to the latest.
I am mostly using it to render HTML so I don't really use any fancy React API.
|
Released as 5.5.0-beta-1, would be great if people gave it a spin and reported how they like it. |
|
Will need a bump there too. |
|
I'll try to give this a look tonight. |
|
@MangelMaxime I created HMR PR as well elmish/hmr#48 |
As we are trying to fix root remounting, should we try to fix it for HMR too? When applying HMR we are getting:
I believe this is because every time HMR trigger are re-running the let root = ReactDomClient.createRoot (document.getElementById placeholderId)A solution to that problem would be to attach the // Pseudo code (can probably be done with `match ... with`
let rootElement = document.getElementById placeholderId
let root =
if isNull (rootElement?__elmish_root) then
let root = ReactDomClient.createRoot root
rootElement <- root
root
else
rootElement?__elmish_rootIn theory, this should allow React to correctly unmount the previous React components. I don't know if this could have unwanted side effects or not, it would avoid having a warning in dev mode, confusing some new users. |
|
@kerams Maxime has published the HMR beta, could you give it a spin? |
|
Guess I'll merge this and we can do another round of changes as needed for GA. |
|
So far so good. Anything I should watch out for? |
|
@kerams not in particular, thanks for pointing out the HMR issue. |
|
Sorry I didn't get to this sooner. You move fast. Looks good to me. Testing will tell the tale. |
Fix root remounting and modernize lazy views with React.memo
Summary
Replaces the class component-based
LazyViewimplementation with React'smemoAPI, fixes root element remounting on each render loop iteration, and introduces awithKeyhelper for element reconciliation. Closes #14 (however suboptimally).Changes
Core: Replace
LazyViewclass component withReact.memo(src/common.fs)LazyProps,Components.LazyViewclass component, andInternal.ofTypehelperlazyViewWith,lazyView2With, andlazyView3Withnow create memoized functional components viaReact.memowith a JS-level__memostamp on the view function for stable component identitydisplayNamefor better React DevTools experiencelazyView2WithandlazyView3Withnow return curried functions — designed for partial application (let render = lazyView2With equal view) so the memo component is created once and reusedMemoProps1/MemoProps2record types to carry model/dispatch/equal through memo propswithKeyfunction to set React keys on elements, enabling sibling differentiation for memo components (See if we can movekeyprop from a view we're wrapping into the element produced bylazyView#14)Program: Fix root remounting (
src/react.fs)withReactBatchedUsing,withReactSynchronousUsing, andwithReactHydrateUsingnow partially applylazyView2Withonce at setup time rather than on everysetStatecallTests: Comprehensive test suite
tests/LazyViewTests.fs— 351 lines covering:lazyViewvariants__memostampingdisplayNamepropagation from named F# functionswithKeycorrectness, type preservation, and keyed reorder without remounttests/Helpers.fs— Test utilities (flushSync,getDisplayName,getElementKey, etc.)tests/DisplayNameViews.fs— Named view functions for displayName assertionstests/Main.fs/tests/Tests.fsproj— Test runner setup with Fable + Mocha + jsdomInfrastructure
react/react-domfrom^17.0.2to^18.0.0mocha,jsdom,global-jsdomdev dependenciesnpm testscript.config/dotnet-tools.jsonfor local tool manifestReact DevTools Components view post-optimization