-
-
Notifications
You must be signed in to change notification settings - Fork 715
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Race condition in simple example app #538
Comments
There is actually nothing wrong with this approach in many situations. This tutorial: https://purelyfunctional.tv/guide/state-in-re-frame/ broadly covers the nuances of various strategies for managing state. For forms, it is very sensible to have a component local reagent atom store any change to the form inputs, and also have a button that could dispatch the global sync event. |
Maybe, but splitting the state (component local and global) can leads to inconsistencies and very messy code. I was hoping that in case of the simplest and most frequent work patterns good examples will be provided where everything should work reliably. |
I would suggest you look at a library like re-com. Some of its components have local state and it works without problems or messyness. |
Thanks for reply. Should we replace hand-written components from example app by re-com components as soon as only an expert (e.g authors of re-com) can writes them correctly? Should we highlight the problem of race conditions and how to avoid them in docs? |
You requested good examples, yes? I believe they were supplied. You expressed concern about how code might get messy, and I believe the example shows how to avoid it. As far as I can tell your final request is that we add an FAQ entry, yes? |
Yes, it would be great. And fix example app. |
The next time I push FAQs there will be a new one covering this subject. The text currently looks like this ... QuestionMy input field is laggy. When the user types quickly, it is dropping characters. I have implemented it like this: [:input.input
{:type "text"
:value @(rf/subscribe [::subs/username])
:on-change #(rf/dispatch [::events/change-username (-> % .-target .-value)])
}] AnswerThat
Bottom line: with high-speed typing, characters can get dropped. There are three solutions:
|
In "Simple example" app we can see regular example of binding input value of the DOM input element with app state and reading "proposed value" in on-change event from target.value.
https://github.com/Day8/re-frame/blob/ce4c580dfc24e120b932f4aebf000a85b426543e/examples/simple/src/simple/core.cljs#L72
https://github.com/Day8/re-frame/blob/ce4c580dfc24e120b932f4aebf000a85b426543e/examples/simple/src/simple/core.cljs#L73
But applying this pattern can leads to inconsistence in UI when a user types faster, then app state syncs with DOM input element. Is is not only about UI hangs but about stale app state reads: typing a string in input a user can finished with string which is subsequence of the original string.
Just try to add the following code (an argument value change is probably necessary for different machines) to event handler which updates app state:
(reduce * 1(range 5000000))
It can leads to very bad UX: imagine that a user fills in a field with a new password without seeing its content, and due to this problem some kind of mess is going to the server :)
This is because target.value mutates by user (when it types charecters) and by re-frame at the same time. The problem was previously discussed in #39 and proposed solution was to use
dispatch-sync
insteaddispatch
in on-change event.Another way to solve the problem is to use reagent atom for reading "local" component state and use subscribptions and event handlers only for global sync, but this violates the whole harmony of the state work approach described in this library and complicates the code even for the most primitive cases. Or maybe we should avoid using
on-change
event at all and starts handleon-key-pressed
event instead, but it is not easy at all.To be honest, I'm confused.
Any suggestions on how to solve this problem are welcome. Perhaps this issue should be covered at least in the FAQ section.
The text was updated successfully, but these errors were encountered: