I'm running into a weird issue that feels like some sort of race condition.
I basically have a master/detail view. So, I click on an entry and load/create its form.
When I quickly switch between items, sometimes the state-machines or rather, the form-state it points to, get's "out of sync".
Meaning, all :event/attribute-changed
do not result in a diff.
I just now observed that the form-state
of those "out of sync" forms are missing all my form-fields
.
Instead, the ::form/id
field (the qualified attr key of the identity attribute) shows up in its config.
(edit: I just noticed the subforms are missing too)
;; What I expect
{...forms-by-ident
{[my ident] {form-state/fields #{:my/name :my/other-thing}}}}
;; What I actually _sometimes_ get
{...forms-by-ident
{[my ident] {form-state/fields #{:my/id}}}}
This is super strange because I don't do anything with those forms besides starting them on :will-enter
.
I traced it back to https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/form_state.cljc#L198.
The only idea I have right now, is that prop-keys
inside https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/form_state.cljc#L106
sometimes doesn't have my fields (?) so that the result of (set/intersection all-fields prop-keys)
is wrong. But that's just a wild guess right now.
Any ideas what might cause this, or where I could look further?
edit: found a hacky workaround for now, but i'd still be interested to solve this properly.@rob703 my guess is you’re not using the will-enter properly or have some other timing error
I'm calling rads form/form-will-enter
in my own will-enter. But I'll look further into my timing & network graph. Maybe some other thing messes up my routers timing
in a deferred route?
There's some nesting going on with deferred routes yes.
The problematic form component is SelectedNode
it's the one ending up with broken form configurations. As you can see I'm leveraging/mixing RAD with standard fulcro for various reasons.
So, from your question I assume nesting deferred routes could lead to timing issues?
As a matter of fact I experience more issues on form loads with higher latencies.
(My form loads can get quite heavy and I'm still in the process of optimizing it. So latencies around 300-500ms are quite common right now.)
I was thinking about enabling aborts for all my loads, so I can at least cancel everything when I switch forms while an old one is still loading. Do you think that would help?
Nesting a form that expects to be used as a top level route is fine, but using will-enter on it when it isn't a route target seems questionable. You should look at that function and pull out the non-routing bits. Not sure what else you might be doing, but remember that async has no order guarantee, so if you're letting the ui drive that without some race control then bad things can happen. So yes, cancellation of the in-flight request seems prudent.
Well, async in std fulcro on a single remote does have an order guarantee, but if you make the destination a moving target you're also asking for trouble
I constructed my application by copying a template I saw somewhere. I can't find a link to the exact one, but I'm pretty sure I didn't invent this on my own. I start by mounting a Root component on the global app state. This Root component has a SiteChrome component. Root has an :initial-state function that calls (get-initial-state SiteChrome). SiteChrome has a SiteRouter component. SiteChrome has an :initial-state function that calls (get-initial-state SiteRouter)
. SiteChrome then renders the SiteRouter factory using its props. I wouldn't be surprised to learn there's a more efficient way to do this, but this has worked without issue until now. I'm trying to extend this to add a Session component that validates a token against a remote, if a token exists. I've added this Session component to SiteChrome along with SiteRouter. I'm assuming I should be able to trigger a remote mutation in the :per-merge hook of the Session component, using the query passed to this hook. However, I don't see any evidence that this hook is being called. I have a tap setup with shadow inspect and nothing shows up. It appears as though the :pre-merge hook is not being called on the Session component. I also see the following error in the browser's debug console:
> core.cljs:159 WARN [com.fulcrologic.fulcro.ui-state-machines:215] - Attempt to get an ASM path [:com.fulcrologic.fulcro.ui-state-machines/local-storage :path-segment] for a state machine that is not in Fulcro state. ASM ID: :fulcro-app.ui.components/SiteRouter
> #error {:message "", :data {}}` I wonder if the two problems are related?
What I'm trying to do is effectively "ping" a remote and alter client state when the application is loaded. Is what I've described above the best way to achieve this? If not, what is? Thanks.
I wouldn't side-effect in pre-merge
FYI. What you essentially want is a mutation with returning, or a load with post mutation/action. The logic should not be part of data merge or component lifecycle. Auth is logic to build outside of the ui. Ok to use components to represent the queries and io for that, but I'd recommend a uism for the logic
Thanks @tony.kay. I do have a state machine as well. I'll add what I need there. I misread the documentation. Thanks
Anyone else having problems with fulcro-inspect in Chrome 86.0.4240.183
? No errors reported in the background page
Fulcro version?
2.8.13
you have to manually install from releases. See pinned items in #fulcro
new version is not bw compat
Sorry, didn’t see that! The problem is my company blocks the installation of unpacked extensions. I will see what I can do about it
If I can’t do anything about the blocking would you mind if I fork and publish in chrome store under some name like fulcro-inspect-for-fulcro-2 or something like that (we don’t care about the name)? Respecting the terms of the license of course
We can also choose the private option when publishing so there wouldn’t be two versions available in the chrome store
I now see something. I'm getting a run-time error about wrong number of args passed to the SiteChrome factory. I'll do some digging. Sorry for the distraction
It works in Chrome Canary version 88.0.4315.0
, but not in the stable
I just found some interesting behavior that may or may not be intentional. When calling begin!
multiple times in quick succession, the ::uism/started
event is invoked multiple times (expected) without applying the uism/activate
(unexpected). e.g.
(defstatemachine eg-sm
{::uism/states
{:initial {::uism/handler (fn [env]
(print "Still here...")
(-> env
(uism/activate :state/idle)))}
:state/idle {::uism/handler (fn [env] nil)}}})
(begin! ...)
(begin! ...)
(begin! ...)
;; console
Still here...
Still here...
Still here...
My assumption is that the atom isn't keeping up somehow. If this is a bug I can try to chase it down more. Otherwise I'll leave it be and fix my side.I see nothing unexpected in your example. Begin (re)starts the machine when you call it. That is a defined behavior
ah, ok. I thought it was intended to be like uism/transact! ::uism/start ...
, but the restart semantics make sense
yeah, begin means begin 🙂 It’s not an event, it’s a complete initialization.
Maybe it is related to some of the rewrite performed in this commit?
https://github.com/fulcrologic/fulcro-inspect/commit/8648394b80f600ed2b6f6c533969967c9efc2fa1
When checking out commit 5e982f9961d8c0fd0717ccde6aa2e636f0fa6b55
things start to work again.
I’ve noticed some postMessage events or data seem to not be available like init-history-step attribute or the event db-changed!