Fork me on GitHub
#fulcro
<
2023-09-29
>
tony.kay17:09:53

Doesn’t seem like you’ve got the state management working yet?

tony.kay17:09:09

(ns test1
  (:require
    [com.fulcrologic.fulcro.application :as app]
    [com.fulcrologic.fulcro.components :as comp :refer [defsc]]
    [com.fulcrologic.fulcro.mutations :as m]
    [com.fulcrologic.fulcro.dom :as dom]))

(defonce app (do (println "Def app!") (app/fulcro-app)))

(defsc Counter [this {:ui/keys [n]}]
  {:query [:ui/n :counter/id]
   :ident :counter/id
   :initial-state (fn [_] {:counter/id 1 :ui/n 1})}
  (dom/button {:onClick
               (fn [evt]
                 (m/set-integer! this :ui/n :value (inc n)))}
    (str "N:" n)))

(def ui-counter (comp/factory Counter))

(defsc Root [this {:keys [counter]}]
  {:query [{:counter (comp/get-query Counter)}]
   :initial-state (fn [_] {:counter (comp/get-initial-state {})})}
  (dom/div
   (dom/h3 "Hello from Fulcro!")
   (ui-counter counter)))

(app/mount! app Root "demo-app") ; <1>

Jakub Holý (HolyJak)17:09:11

I haven’t tested it 😅

tony.kay17:09:12

doesn’t seem to work

Jakub Holý (HolyJak)17:09:28

Thank you! I will look into it as soon as I can

tony.kay17:09:29

wonder how we’d get inspect to work

tony.kay17:09:51

w/o inspect it would be rather painful to debug anything of any complexity

💯 1
Jakub Holý (HolyJak)17:09:09

Yeah, me to. Isn’t it enough to issue some call to get it hooked in? I am not sure how it works underneath…

tony.kay17:09:04

It thinks the component has no ident

tony.kay17:09:16

I’m getting a “mutation set props missing ident” error in console

Jakub Holý (HolyJak)17:09:49

My rewrite of the defsc macro could have screwed up, perhaps? I essentially copy-pasted but that might be insufficient

tony.kay17:09:50

and yes, inspect itself is written in (old) Fulcro, and it’s just a comm protocol between the two

tony.kay17:09:19

state database says:

{nil #:ui{:n 1}, :com.fulcrologic.fulcro.application/active-remotes #{}}
so yeah, ident isn’t working for some reason

tony.kay17:09:46

could be a problem with initial state

tony.kay17:09:54

I tried initial state in convenience mode and non convenience, but made a typo there

Jakub Holý (HolyJak)17:09:20

Nice to see that you too are human 🙂

tony.kay17:09:42

I hate this editor, though

tony.kay17:09:50

the paren matching is just making it impossible to edit

Jakub Holý (HolyJak)17:09:46

Thx for the feedback! I have mostly focused on the plumbing and not usage. I am sure there is a ton to improve. I might have messed up integration of clojure-mode …

tony.kay17:09:57

initial state works fine

😌 1
tony.kay17:09:09

it’s ident that has a problem I think

tony.kay17:09:31

both lamda and shorthand version

tony.kay17:09:02

hm…if I call get-ident manually it is ok, though

tony.kay17:09:36

(ns test1
  (:require
    [com.fulcrologic.fulcro.application :as app]
    [com.fulcrologic.fulcro.components :as comp :refer [defsc]]
    [com.fulcrologic.fulcro.mutations :as m]
    [com.fulcrologic.fulcro.dom :as dom]))

(defonce app (do (println "Def app!") (app/fulcro-app)))

(defsc Counter [this {:ui/keys [n] :as props}]
  {:query [:ui/n :counter/id]
   :ident :counter/id
   :initial-state {:counter/id 1 :ui/n 1} }
  (dom/button {:onClick
               (fn [evt]
                 (m/set-integer! this :ui/n :value (inc n)))}
    (str "N:" n)))

(def ui-counter (comp/factory Counter))

(defsc Root [this {:keys [counter]}]
  {:query [{:counter (comp/get-query Counter)}]
   :initial-state {:counter {}}}
  (dom/div
    (dom/h3 "Hello from Fulcro!")
    (dom/div (pr-str (app/current-state this)))
    (dom/div (pr-str (comp/get-initial-state Root {})))
    (dom/div (pr-str (comp/get-ident Counter {:counter/id 3})))
    (ui-counter counter)) )

(app/mount! app Root "demo-app") ; <1>

tony.kay17:09:54

the component looks fine

tony.kay17:09:13

(defsc Root [this {:keys [counter]}]
  {:query [{:counter (comp/get-query Counter)}]
   :initial-state {:counter {}}}
  (dom/div
    (dom/h3 "Hello from Fulcro!")
    (dom/div (pr-str (app/current-state this)))
    (dom/div (pr-str (meta (comp/get-query Counter))))
    (dom/div (pr-str (comp/get-ident (:component (meta (comp/get-query Counter))) {:counter/id 44})))
    (dom/div (pr-str (comp/get-initial-state Root {})))
    (dom/div (pr-str (comp/get-ident Counter {:counter/id 3})))
    (ui-counter counter)) )

tony.kay17:09:40

The component is in the metadata of the query, and the get-ident works just fine from that component to generate an ident

tony.kay17:09:34

ok, now I’m really stumped. db->tree works

tony.kay17:09:10

There’s nothing wrong with the component or the base internal algorithm for normalization. Something about mount itself?

tony.kay17:09:33

(defsc Root [this {:keys [counter]}]
  {:query [{:counter (comp/get-query Counter)}]
   :initial-state {:counter {}}}
  (let [s (norm/tree->db Root {:counter {:counter/id 5}} true)]
  (dom/div
    (dom/h3 "Hello from Fulcro!")
    (dom/div (pr-str s))
    (dom/div (pr-str (app/current-state this)))
    (dom/div (pr-str (meta (comp/get-query Counter))))
    (dom/div (pr-str (comp/get-ident (:component (meta (comp/get-query Counter))) {:counter/id 44})))
    (dom/div (pr-str (comp/get-initial-state Root {})))
    (dom/div (pr-str (comp/get-ident Counter {:counter/id 3})))
    (ui-counter counter))))

tony.kay17:09:10

So, summary of my findings: • Component itself seems ok. query, initial state, embedding of component on query, ident. • Normalization alg works fine when invoked manually

tony.kay17:09:01

component registry is empty

Jakub Holý (HolyJak)17:09:07

I would suspect that I did something wrong when rewriting macros into SCI (it was almost only copy-paste, but this does’t always yield the expected result)

Jakub Holý (HolyJak)17:09:30

Ah, yes. Comp. registry is a dyn var, and they are special.

tony.kay17:09:49

class->registry-key on Counter returns :/Counter

tony.kay17:09:02

so the macro pulling the “current ns” to make the registry key is broken

Jakub Holý (HolyJak)17:09:18

Though we should only be setting it from code the SCI script (the content of the editor) invokes, no? Unless defsc expands into code that tries to set it…

tony.kay17:09:22

and for hot code reload support the components use the registry to pull the updated query (or dynamic even)

tony.kay17:09:15

These two lines in defsc*:

nspc                             (if (cljs? env) (-> env :ns :name str) (name (ns-name *ns*)))
           fqkw                             (keyword (str nspc) (name sym))

tony.kay17:09:42

in CLJ assumes *ns* will work, in cljs the compiler has that in &env. Don’t know for sci

Jakub Holý (HolyJak)17:09:44

Yep, for some reason, sci env lacks :ns LEt me fix it…

tony.kay17:09:22

This is true on all of the component generating things. They need to be able to figure out the ns to make the registry key

tony.kay17:09:33

sci won’t let me look at the component-registry (marked private)

tony.kay17:09:42

so I’m not sure what is in it if anything

tony.kay17:09:49

but that would cause the misbehavior I’m seeing

tony.kay17:09:31

If I look up the class with :/Counter I do get something back, so even though it is wrong, I think perhaps that isn’t causing the normalization problem. I can call get-query on it, and it works, so it seems like it is a functioning component. So, it may or may not be the root cause of the problem.

Jakub Holý (HolyJak)17:09:45

Using development.cljs in my sci.configs, with this code in the init fn (copy of yours), I get the updates when I click the button:

(sci/eval-string* full-ctx "
    (do
      (ns test (:require 
        [com.fulcrologic.fulcro.dom :as dom]
        [com.fulcrologic.fulcro.mutations :as m]
        [com.fulcrologic.fulcro.application :as app]
        [com.fulcrologic.fulcro.react.version18 :refer [with-react18]]
        [com.fulcrologic.fulcro.algorithms.normalize :as norm]
        [com.fulcrologic.fulcro.components :as comp :refer [defsc]]))
(defonce app (-> (app/fulcro-app) with-react18))
                              
(defsc Counter [this {:ui/keys [n] :as props}]
  {:query [:ui/n :counter/id]
   :ident :counter/id
   :initial-state {:counter/id 1 :ui/n 1} }
  (dom/button {:onClick
               (fn [evt]
                 (m/set-integer! this :ui/n :value (inc n)))}
    (str \"N:\" n)))

(def ui-counter (comp/factory Counter))
                              
  (defsc Root [this {:keys [counter]}]
  {:query [{:counter (comp/get-query Counter)}]
   :initial-state {:counter {}}}
  (let [s (norm/tree->db Root {:counter {:counter/id 5}} true)]
  (dom/div
    (dom/h3 \"Hello from Fulcro!\")
    (dom/div (pr-str s))
    (dom/div (pr-str (app/current-state this)))
    (dom/div (pr-str (meta (comp/get-query Counter))))
    (dom/div (pr-str (comp/get-ident (:component (meta (comp/get-query Counter))) {:counter/id 44})))
    (dom/div (pr-str (comp/get-initial-state Root {})))
    (dom/div (pr-str (comp/get-ident Counter {:counter/id 3})))
    (ui-counter counter))))
      (app/mount! app Root \"app\"))
    ")
but this is in shadow dev mode, could differ in :advanced

tony.kay17:09:05

it does work…it’s that your hot code reload isn’t working 😄

👍 1
tony.kay17:09:16

I reloaded the page and it is fine, though the registry keys are wrong

tony.kay17:09:51

wait, not fine…it initialized correctly, but it still won’t let me run the mutation. still says ident is missing

tony.kay17:09:57

but normalization worked

tony.kay17:09:16

OH WAIT: No it didn’t

tony.kay17:09:19

I read the wrong line

tony.kay17:09:50

The current state is completely empty now

tony.kay17:09:22

It updates when I hit the button to have junk

tony.kay17:09:31

but only one I re-eval the code

tony.kay18:09:49

So, yeah, updated summary: • Initial state is nil on first mount • CMD-Enter on updated code (after trying a mutation) has someething in db • So, it is initialization of the first frame db that is not happening at all

tony.kay18:09:43

In terms of “Inspect”. Just having a formatted db you can look at is probably good enough, and that’s easy enough to do.

👍 1
Jakub Holý (HolyJak)18:09:10

Where / how is initial state nil on 1st mount? When using the sci.configs development.cljs, and evaluating the code above from init + reloading the page, I get current state =

{:fulcro.inspect.core/app-id "/Root", :counter [:counter/id 1], :counter/id {1 {:counter/id 1, :ui/n 1}}, :fulcro.inspect.core/app-uuid #uuid "e0f73551-f2a4-4788-aeff-f498f7cc6148"}
so it is not empty?

Jakub Holý (HolyJak)18:09:02

I do not see the problem. Where should I look? When I get the html from https://gist.github.com/holyjak/4c7048f2fe385c1ae826c6603fbcb560 and serve it with e.g. python3 -m http.server 8888 then http://localhost:8888/dev-editor.html renders

{:counter [:counter/id 5], :counter/id {5 #:counter{:id 5}}}
State{:fulcro.inspect.core/app-id "/Root", :counter [:counter/id 1], :counter/id {1 {:counter/id 1, :ui/n 1}}}
{:component #object[Function], :queryid "/Counter"}
[:counter/id 44]
{:counter {:counter/id 1, :ui/n 1}}
[:counter/id 3]
N: 1
which looks fine? What am I missing? (Though the missing ns obviously still is wrong, but at least it is missing consistently everywhere)

Jakub Holý (HolyJak)18:09:28

BTW I see why the ns is missing, I assumed that it was a string but it should be a map with :name …

Jakub Holý (HolyJak)18:09:05

FYI pushed a fix for the missing namespace, and https://blog.jakubholy.net/js/code-editor.js is updated with the fix

Jakub Holý (HolyJak)18:09:35

To summarize, I do not know how to replicate Initial state is nil on first mount and/or hot code eval issues 🙏

tony.kay18:09:03

I was working in your blog post

tony.kay18:09:09

mayebe it’s just the blog post version?

Jakub Holý (HolyJak)18:09:13

It works there now, it seems to me. Just make sure to not use cached version of code-editor.js