-
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
Set root component state instead of calling RenderDom for every update #10
Conversation
Would you mind running performance test, with something like this. |
I cloned the repo but there are no instructions to build the tests. Do you know how to do it? |
@alfonsogarciacaro I had already added Elmish test some months ago in my fork. Please take a look at the 2 last commits. You will probably need to update the Fable version, etc. because it's outdated but you will got the basic idea of how to add a new test. |
Thanks @MangelMaxime! It seems I couldn't run the tests because |
@alfonsogarciacaro Have you tried with input's Value ? After adding Looks in newest React it's already using |
@zaaack Yes, input's
About the link to the React code, I didn't follow the references but in the comment on the top of the file it says that's a polyfill for
That makes me wonder whether this is actually used for |
@alfonsogarciacaro The input's Value doesn't work in my here after I change your raf code to: match rootEl with
| Some _ ->
// observable.Trigger(model, dispatch)
match lastRequest with
| Some r -> window.cancelAnimationFrame r
| None -> ()
lastRequest <- Some (window.requestAnimationFrame (fun _ ->
observable.Trigger(model, dispatch))) I didn't look deeply into React's source code, and cannot give some strong evidence that React using requestIdlCallback to batch setState. But I think it's not a big problem since we can easily add a new ui test case to find out the performance difference. |
@zaaack Ah, you're right. The cursor is jumping to the end if |
src/react.fs
Outdated
/// Setup rendering of root React component inside html element identified by placeholderId | ||
let withReact placeholderId (program:Elmish.Program<_,_,_,_>) = | ||
let mutable rootEl = None |
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.
local state might break hmr, https://github.com/fable-elmish/react/pull/6/files#diff-6e208d7e773cd65ba4c7e6cf6adde006R36 maybe it's better to be put in module level?
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.
Makes sense, thanks! I was also thinking that a boolean flag (like let mutable initialized = false
) is probably enough here 👍
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.
I tried move the local state to global, remove shouldComponentUpdate
, but it's strange that I cannot get HMR working with you implementation. you can try it with my demo repo by replace paket-files/zaaack/react/src/react.fs
with yours and edit Home/View
: https://github.com/zaaack/elmish-react-demo
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.
Hi @zaaack! I just did that: cloned your demo and replaced react.fs with the code here (also uncommented the |> Program.withHMR
line in App.fs) and HMR worked without problem. The only change needed is to remove shouldComponentUpdate
so I guess we can wrap it #if !DEBUG
to keep it in Release mode. Note I didn't have to make any state global.
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.
@alfonsogarciacaro I tried what you said before, but the view doesn't change if I edit a string child of a ReactElement, and also no errors.
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.
Don't know ..
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.
I would vote for not using requestAnimationFrame
...
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.
@alfonsogarciacaro I tried my react.fs and hmr works for update. And also yours after making local state to global state like this:
(Sorry for the downcast, I don't know how to get around Value restriction
and just for a quick example, so ... 😅)
open Fable.Import.Browser
let mutable observable = None :> obj
/// Setup rendering of root React component inside html element identified by placeholderId
let withReact placeholderId (program:Elmish.Program<_,_,_,_>) =
let setState model dispatch =
match (observable :?> SingleObservable<_> option) with
| Some obs ->
obs.Trigger(model, dispatch)
In my case local state are lost after hmr, but in your code it's initialized again, it can be easily find out by adding some logs. But still don't know why your logical code are not update?
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.
I think I'm getting a bit lost ;) I don't see any difference by placing observable
on the top level. But yes, I can confirm requestAnimationFrame
is what causes the jumping cursor issue, if I add it to these lines then the problem appears again.
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.
168a498
to
d873f21
Compare
So, how is the perf looking? |
Actually, forget performance. Can you put the old impl back in, just name it something like |
That's a great idea @et1975! I assume keeping the old implementation means also keeping About performance, I haven't managed yet to make this work with the test project (see above), I'll see if it can be fixed 👍 |
@alfonsogarciacaro I think he means to not touch the Like so users have the choice. |
Either way, just as long as there's a choice. |
Ok, I finally found why the tests didn't work, the runner is submitting However, removing |
Thanks for your effort to fix this issue! I can confirm Maybe there are some info that I forgot to mention, this "glitch" would cause asians (like me) who write CJK with IME cannot input any character, we have to using the workaround anywhere. Perhaps that's also why there are not much feedback about this problem... But still, thanks a lot! |
Thanks to you for such a thorough testing @zaaack I also use CJK with IME (though I hadn't tried with an Elmish app yet) so I agree this is a strong reason to fix the glitch (I also fixed something similar in Fable). What do you think @et1975? If that's ok, I will edit the PR so it just removes |
For backwards compatibility, let's have 2 functions to init react: |
29e2a99
to
0d12c81
Compare
0d12c81
to
8c8adc1
Compare
Sorry, I should have just updated the PR to make the intention clearer. I just did it and as you can see, the (last) proposal is to only remove I run the tests again, and this PR is also slower, but I guess What do you think? |
Hmm, weird! So this must have been a regression when I introduced the RAF optimization... |
I am a bit loss here. In the latest state of this PR what is it trying to solve ? Because, at first it was about using Aparté |
@MangelMaxime Yes, this and #6 where originally intended to use
@et1975 Following your previous suggestion, I've modified the PR to keep the original implementation and offer an alternative with the explanation. I also opened #12 to keep better track of the issue and try to investigate the real cause of the problem 👍 |
I've released this as 1.0.1-beta-1, please hard reset on origin/master as I've squashed all those commits to keep the history clean. |
Alternative to #6