-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using setState to render the view #6
Conversation
3a18310
to
d41d13b
Compare
@et1975 For info, And I can't use it on a simple input, it's failing at runtime with |
@MangelMaxime Can you try it again? Looks I ran into some fable issue maybe? it works now in my elmish-react-template app. Didn't notice HMR is breaking, I'll see what I can do. |
Looks like the previous code triggered a wired code from repl: export const hasUpdate = defaultArg(defaultArg(lastModel, null, function (a) {
return !(model === a);
} /*a function */), true); code from webpack: var hasUpdate = Object(__WEBPACK_IMPORTED_MODULE_8__nuget_packages_fable_core_1_3_0_fable_core_Option__["b" /* defaultArg */])(Object(__WEBPACK_IMPORTED_MODULE_8__nuget_packages_fable_core_1_3_0_fable_core_Option__["b" /* defaultArg */])(lastModel, null, function (a) {
return !(model === a);
}())/* an IIFE */, true); Still trying to understand how HMR works. ===== Update ==== This bug comes from fable, I repoduced it with fable-splitter and dotnet-fable 1.3. Just created an issue in fable. @alfonsogarciacaro |
@MangelMaxime Now HMR is working, again! Thanks a lot for your test! |
src/react.fs
Outdated
|
||
member this.render () = | ||
printfn "render" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this debug log :)
HMR seems to works, and I don't see performance problem from my tests. Will let Eugene take the relay from now. |
@MangelMaxime Updated! |
Clearly some optimization is taking place, but apparently in React impl it happens at model->VDOM stage, instead of VDOM->DOM (as Preact appears to be doing it). If that's the optimization you want why not implement that specifically - a function that takes some state ( The only reason Native impl uses an app component is because Native doesn't work without. It's ugly and it was a massive pain to get it to work properly. Looking at your code I have no confidence that it will work correctly and you are not inspiring any by letting others find the issues instead of doing thorough testing yourself. Specifically, I find the use of rendered In general, not that I don't appreciate the effort, but the issue you are fixing is closed and the discussion around it clearly amounts to "there are known workarounds" not "send the PR!". My suggestion is to keep this as a separate implementation of React renderer, in your own library. |
et1975 Thanks for your patient explanation. What do you mean I know maybe this looks a little hacky, but it totally followed the React's core API 😉. And In my imagine it should works like a drop-in replacement for original implementation, the root component (App) only rendered by ReactDOM.render once, so I don't need to wrap it with lazy view, I only wrapped it's children with lazyView. React don't do model diff in default, so there should be no cost in putting a big view into state (maybe different in RN? but I think I can wrap it with a function if it's better), since it will just update the view after calling This also won't break React's
To be clear, there are two main concerns of this PR:
But I totally agree that this need more feedback and testing, especially elmish-react have a big ecosystem and this is also a breaking change. Maybe release in alpha or beta channel? I'll definitely try and test it with my current fable project. Update: view has already been wrapped by a render function when passing to state. |
Maybe you could push a package with a different name and let users test it to give you feedback, @zaaack? I'm a bit concerned that in this PR |
@alfonsogarciacaro Publishing a fork version is a choice, but I don't have confidence I can get enough feedback from a small community for a fork repo. Currently
Update: In newest React, it's already using RAF under the hood. https://github.com/facebook/react/blob/master/packages/shared/ReactDOMFrameScheduling.js#L138 Your observable approach is much clear 👍, either of them getting merged is OK for me. Even if neither of these can, I think I can still reference a fork repo by paket, which others can also help testing. |
For completeness, this is the function that I think replicates the React optimization in its entirety: let inline valueOrDefault value e =
if e |> isNull |> not && !!e?value <> !!value then e?value <- !!value Usage: R.input [Ref (valueOrDefault model.Value); OnChange ... ] |
Just to add to my previous thumbs up, I'm using your code @et1975 and it works in all use cases I've tried so that's great thanks. |
Fix elmish/elmish#60
This issue has been fixed in react long long ago, but it appears in elmish-react now. If we using setState to update the input's value, it won't reset the cursor, because the real input's value after typing is the same as react vdom's, so react won't change the real dom, and cursor won't change. But if we update the view by
ReactDOM.render
, this issue occurred again, so I think we could change to the commonly used way (update the view by setState) in react to keep the consistency.Warning: this is a breaking change, in the original way,
DefaultValue
can work around it just likeValue
in this new way, if you changeDefaultValue
in model, it would update the view, too. But now,DefaultValue
is thedefault value
, and won't sync to view if the view is not first render. If you need to control the input, you should usingValue
instead, which is the same as in normal react app.