Fork me on GitHub
#re-frame
<
2019-10-28
>
dominicm09:10:38

I'm trying to understand the internals a little better, because I'm seeing unexpected behavior. I'm calling dispatch-sync to update a value in my app-db. I'm calling this on willMount. A child component then subscribes to this data. However, on first render it shows the old value, then a re-render happens with the new value. This is problematic as the child component stores the first value it sees into a local atom for UX-related post-processing. Am I missing some important incantation, or is this simply how reframe works?

jahson12:10:40

It might be related to order of events happening. I'd try to log every related event, like mount and dispatch, for all components.

jahson13:10:06

So, the order is, like, willMount, childDidMount, dispatch-sync?

dominicm13:10:04

I logged: - After dispatch-sync - After subscription deref (which is in render) Order is: - dispatch-sync - subscribe (old value) - subscribe (new value)

danielneal13:10:50

I’m guessing that although dispatch-sync runs the event handler synchronously, the recomputation of the subscriptions is not done as part of that synchronous block, so the subscribe in the child will see the cached value on its first render

danielneal13:10:26

can you move the will mount logic outside of the component, and choose whether to show the component based on a subscription

dominicm13:10:54

Unfortunately not. I'm interfacing with a react component that passes a "cause trigger" in the props which I need to react to in order to change the input initial value.

jahson13:10:49

So, the question is why the subscription computes twice.

jahson13:10:38

Oh, the log was done after subscription deref, not in subscription itself.

dominicm13:10:21

I didn't dig in far enough to see what happens with the app-db from the handler-fn. I didn't check when it was actually swapped back.

dominicm14:10:04

I guess the intention is to provide a consistent view of the state until after the render has completed?

jahson14:10:17

Can you isolate the case somehow? Like, just the parent component that fires dispatch-sync in will-mount and the child element that subscribes?

dominicm14:10:24

I don't understand what you mean sorry.

dominicm16:10:44

having dug in, I can't find anything that would imply that there's something special to make it be consistent in re-frame. So my only other conclusion would be it's clojure/reagent behavior somehow.

dominicm17:10:26

Okay. Looks like this is reagent behavior. I haven't quite read the source to understand the context, but a call to ratom/flush! does the trick.

mhuebert20:10:48

I believe reagent runs ‘flush’ once per render loop (before looping through all the invalidated components and .forceUpdate’ing them), and the flush is what forces the stale subscriptions to update, so I think you have found the best path forward

lilactown21:10:34

interestingly, the problem @kenny @mikethompson and I discussed above about debouncing is directly related to a new API that the React team is experimenting with: https://reactjs.org/docs/concurrent-mode-patterns.html#deferring-a-value

lilactown21:10:09

(sorry oconn for the [email protected]; I mis-remembered 😅 )