Fork me on GitHub
#hyperfiddle
<
2024-05-28
>
nakkaya23:05:56

I am working on a custom type that implements IAtom IDeref IRef IMeta IObj IReference . It acts like an atom but the data is synced to a database. I can use it like the following,

(e/defn Counter []
  (let [state (e/server
               (e/watch
                (my-atom 0)))]
    (e/client
      (dom/p (dom/text state)))))
which works, any updates to the database automatically updates the UI. What I can't get working is the following form,
(e/defn Counter []
  (let [!state (e/server
                (my-atom 0))
        state (e/watch !state)]
    (e/client
     (dom/p (dom/text state)))))
I would like to keep a reference to !state so I can, say from a button callback do something like (e/server (swap! my-atom inc)) . Currently latter form results in Unserializable reference transfer.

Dustin Getz00:05:45

likely the watch is client sited causing an undesired transfer, due to calling Counter on the client

nakkaya08:05:56

Is there a workaround you can suggest? @U09K620SG I would like to avoid having a top level (e/def !state)

xificurC08:05:14

(e/defn Counter []
  (e/server
    (let [!state (my-atom 0)
          state (e/watch !state)]
      (e/client
        (dom/p (dom/text state))))))

nakkaya08:05:32

@U09FL65DK thanks that did it 👍

😉 1
xificurC08:05:45

do you understand why?

nakkaya08:05:47

my understanding is, both atom-like and watch is constructed server side then only watch is transferred back to client, which was also my intent in the first form, third form actually hinted the electric to actually do it?

xificurC08:05:15

atom - reference type, cannot be serialized. Also, it would imply client could reset! a server atom (e/watch atom) - reactive deref, returns latest value of the atom. Typically the value inside is serializable Your second snippet constructs a server-side atom and attempts to watch it on the client, which would require transfering the atom itself

👍 1