Fork me on GitHub
#fulcro
<
2020-02-28
>
Jakub Holý (HolyJak)07:02:21

How does re-render after transact! work, i.e. how does Fulcro know which components to refresh? Is it so that it simply looks at the this component passed to transact!and refreshes it? If I change data that is used by other components, how to tell it to refresh those? What I have is this tree:

OffboardingPages - queries for [:global/offboarding '_]
                 - passes the `offboarding` as a computed prop to the router below it:
  (ui-base-router router offboarding) -> target comp. BusinessInformationPage:
    (defsc BusinessInformationPage [_ _ offboarding] ...
      (ui-information info offboarding) -> (defsc Information [_ _ offboarding] ...

Inside Information: 
 (comp/transact! this [(mut/finalize-offboarding {:offboarding-id (:id offboarding)})])

Inside mut/finalize-offboarding:
 (swap! state assoc-in [:offboarding/id offboarding-id :finalized?] true)
I see from the log that a render is scheduled and a transaction with ident of the Information component is processed and the DB is updated as expected. However the BusinessInformationPage is not re-rendered. How to fix? Update: I have replaced (comp/transact! this ... with (comp/transact! APP ... but the B.I.P. component still does not re-render.

mavbozo08:02:36

Fulcro tracks the ident of the components and the data corresponding to those idents. What is the ident of Information comp and does BusinessInformationPage has ident?

Jakub Holý (HolyJak)10:02:13

They have both hardcoded idents,

:ident (fn [] [:component/id :information])}
and
:ident (fn [] [:component/id :company])
so the ident is not related to the data being updated (`[:offboarding/id offboarding-id]`) because there is ever only one "offboarding", for convenience a reference to it is stored under :global/offboarding in the DB (where OffboardingPages reads it).

Jakub Holý (HolyJak)08:02:38

@wilkerlucio Hi, why doesn't the latest Fulcro Inspect have the Elements tab it used to have anymore? I miss it 🙂

wilkerlucio18:02:55

@U0CKQ19AQ do you know about this?

tony.kay18:02:25

oh…I thought it was broken in F3, so I hid it

tony.kay18:02:04

all the code is still there, but was it working with 3???

tony.kay18:02:10

I didn’t think it was

wilkerlucio18:02:37

but maybe it should still show, so F2 users could still use it?

tony.kay18:02:55

ah, feel free. I never use it, so someone else needs to deal with it.

Jakub Holý (HolyJak)18:02:07

I can try to find some time and look into fixing it for F3, perhaps...

Jakub Holý (HolyJak)11:02:16

I have a mysterious problem with router props not being passed down after dr/change-route. I have this component that expects two props, :offboarding-pages/router, :global/offboarding but only gets the latter:

(defsc OffboardingPages [_ {:offboarding-pages/keys [router], offboarding :global/offboarding}]
       {:query            [{[:global/offboarding '_] (comp/get-query OffboardingQuery)}
                           {:offboarding-pages/router (comp/get-query BaseRouter)}]
        :ident            (fn [] [:component/id :offboarding-pages])
        :initial-state    {:offboarding-pages/router {}}}
       (println "OffboardingPages props:" props "router props:" router)
       (ui-base-router router offboarding))
;; (def ui-base-router (comp/computed-factory BaseRouter))
;; (dr/defrouter BaseRouter [_ _]  {:router-targets [...]})
When I first render the page, its works and the println above logs > .. router props: {:com.fulcrologic.fulcro.routing.dynamic-routing/id :app.ui.root/BaseRouter, ...} but if I then trigger dr/change-route to go to the other target component of the BaseRouter, the router props are nil: > router props: nil (As I found out later - see the Updates below - in the first case we get ... :alt0 with all the props while in the second we get ... :current-route with only some props, namely missing the router prop.) At this point, when I ask for db->tree on the Rootcomponent to see the actual data passed down the tree, I see the router data is there just fine (elided):
{:ui/routing-ready? true,
 :global/offboarding [:offboarding/id "DUMMYID"],
 :root/content {:root/router 
                {::dr/id :app.ui.root/OffboardingIdRouter,
                 [::uism/asm-id :app.ui.root/OffboardingIdRouter] {...},
                 ::dr/current-route {},
                 :alt0 {:global/offboarding {:offboarding/id "DUMMYID", ...},
                        ;; SEE? IT IS HERE! 👇
                        :offboarding-pages/router
                        {::dr/id :app.ui.root/BaseRouter,
                         [::uism/asm-id :app.ui.root/BaseRouter] 
                         {::uism/asm-id :app.ui.root/BaseRouter, ::uism/state-machine-id dr/RouterStateMachine, ::uism/active-state :routed, 
                          ::uism/ident->actor {[::dr/id :app.ui.root/BaseRouter] :router}, ::uism/actor->ident {:router [::dr/id :app.ui.root/BaseRouter]}, 
                          ::uism/actor->component-name {:router :app.ui.root/BaseRouter}, ::uism/active-timers {}, 
                          ::uism/local-storage {:path-segment ["default"], :target [:component/id :home]}},
                         ::dr/current-route {...},
                         :alt0 {:info {}},
                         :alt1 {}}}}}}
Updates 1. I see in the Root component props that upon the initial render it has the BaseRouter props. But if I dr/change-routeto a different target of the BaseRouter then suddenly its props aren't there anymore. (This worked 1-2 days ago). But when I run (let [state (app/current-state SPA)] (denorm/db->tree (comp/get-query Root) state state)) then the data includes the BaseRouter data, even after it failed to show up in the UI?!!! So the data is there but somehow, when Fulcro fulfills the root query after the routing, it fails to get parts of it?! 2. A key difference between data from db->tree and props of the Root component is that the former includes [:root/content :root/router ::dr/current-route] {}, [:root/content :root/router :alt0] {:global/offboarding ..., :offboarding-pages/router ...} while the latter includes [:root/content :root/router ::dr/current-route] {:global/offboarding ...} and no`[:root/content :root/router :alt0]`. I.e. the "correct" query has the data under :alt0 while the "wrong" query has them under ::dr/current-route, where it lacks the router data. 3. I am working on replicating the issue on a simpler app created from scratch and failing so far. (I have managed to replicate ::dr/current-route {} and :alt0 {:root/router {..}}but don't know yet what those are after routing, only that the app works.)

4
Jakub Holý (HolyJak)18:02:25

SOLVED: The problem was that I had :will-enter .. (if (data-present app) (dr/route-immediate [:component/id :WRONG]) (dr/route-deferred [:component/id :CORRECT] ..)) i.e. I have used the wrong ident in the if-data-present routing branch. I wish I was better in troubleshooting this...

currentoor20:02:01

@U0522TWDA good news is, by figuring it out you’re getting better at troubleshooting this sort of thing naturally simple_smile

Jakub Holý (HolyJak)20:02:54

Yeah, I am really good at making mistakes I can learn from 😂

currentoor20:02:33

but you are learning from the, that’s what matters

Hojat16:02:02

I have a question How hard it is to work with fulcro I'm new to clojure/script world I was going to use clojurescript for one of my projects and was looking for a way to use generated code for mobile app and also I wanted to have ssr because of the seo things The project is a e-commerce web In my searches I found fulcro and it seems really interesting So I just wanna know how long would it take to master these technologies in some level that can solve some simple problems As mentioned I wanna have a web app with ssr and be able to use codes to generate mobile app too I'm well experienced in JavaScript and react

Frank Henard17:02:48

There was a discussion about this fairly recently. Here's the link: https://clojurians.slack.com/archives/C68M60S4F/p1582466702009900

Frank Henard17:02:08

I'm following the getting started tutorial in the book and getting Exception in thread "async-dispatch-7" java.lang.RuntimeException: java.lang.Exception: Not supported: class .File. Google search didn't find anything helpful

Frank Henard17:02:29

just wondered if I'm using a newer version of Java than suggested. I'll look into that

Frank Henard17:02:45

yes, it seems that's the case $ java -version shows openjdk 11.0.5

Frank Henard21:02:24

I installed clojure via homebrew which installed openjdk version 13, and it appears to. I'm having a hard time figuring out how to point either clojure to a my jdk8, or changing shadow-cljs to use a different clojure

mdhaney22:02:06

Have you tried setting JAVA_HOME in your bash profile?

Frank Henard22:02:05

@U0JPBB10W, yes. At the moment, I'm trying to figure out how to tell homebrew that I already have java installed, so that $ homebrew install clojure doesn't try to install version 13

Frank Henard22:02:41

Here's the contents of the clojure bash script:

[email protected] ~ % cat /usr/local/bin/clojure
#!/bin/bash
JAVA_HOME="${JAVA_HOME:-/usr/local/opt/openjdk}" exec "/usr/local/Cellar/clojure/1.10.1.510_1/libexec/bin/clojure" "[email protected]"
It turns out that it is using the correct JDK, so I guess that's not the problem. And I'm still getting this error when I run $ npx shadow-cljs server and then compile:
Exception in thread "async-dispatch-3" java.lang.RuntimeException: java.lang.Exception: Not supported: class .File

Frank Henard22:02:41

Here's the console messages and stacktrace

adamfeldman23:02:40

Long story short, you may use Homebrew to uninstall Clojure and its automatic openjdk dependency, and re-install Clojure from the Clojure team’s new, official Homebrew tap. The Clojure team recommends using LTS Java releases (currently either 8 or 11).

adamfeldman23:02:00

(after reading the thread in detail, this may not be your issue…but hopefully relevant nonetheless)

Jakub Holý (HolyJak)18:02:51

Try to ask in #shadow-cljs Perhaps something is pulling in a too old/new version of a dependency conflicting with something shadow-cljs needs?

Frank Henard20:02:38

Thanks @U0522TWDA, I'll try that!

Frank Henard21:02:24

I installed clojure via homebrew which installed openjdk version 13, and it appears to. I'm having a hard time figuring out how to point either clojure to a my jdk8, or changing shadow-cljs to use a different clojure

Frank Henard22:02:41

Here's the contents of the clojure bash script:

[email protected] ~ % cat /usr/local/bin/clojure
#!/bin/bash
JAVA_HOME="${JAVA_HOME:-/usr/local/opt/openjdk}" exec "/usr/local/Cellar/clojure/1.10.1.510_1/libexec/bin/clojure" "[email protected]"
It turns out that it is using the correct JDK, so I guess that's not the problem. And I'm still getting this error when I run $ npx shadow-cljs server and then compile:
Exception in thread "async-dispatch-3" java.lang.RuntimeException: java.lang.Exception: Not supported: class .File

Jakub Holý (HolyJak)18:02:25
replied to a thread:I have a mysterious problem with router props not being passed down after dr/change-route. I have this component that expects two props, `:offboarding-pages/router, :global/offboarding` but only gets the latter: (defsc OffboardingPages [_ {:offboarding-pages/keys [router], offboarding :global/offboarding}] {:query [{[:global/offboarding '_] (comp/get-query OffboardingQuery)} {:offboarding-pages/router (comp/get-query BaseRouter)}] :ident (fn [] [:component/id :offboarding-pages]) :initial-state {:offboarding-pages/router {}}} (println "OffboardingPages props:" props "router props:" router) (ui-base-router router offboarding)) ;; (def ui-base-router (comp/computed-factory BaseRouter)) ;; (dr/defrouter BaseRouter [_ _] {:router-targets [...]}) When I first render the page, its works and the println above logs > .. router props: {:com.fulcrologic.fulcro.routing.dynamic-routing/id :app.ui.root/BaseRouter, ...} but if I then trigger `dr/change-route` to go to the other target component of the BaseRouter, the router props are nil: > router props: nil (As I found out later - see the Updates below - in the first case we get ... :alt0 with all the props while in the second we get ... :current-route with only some props, namely missing the router prop.) At this point, when I ask for `db-&gt;tree` on the `Root`component to see the actual data passed down the tree, I see the router data is there just fine (elided): {:ui/routing-ready? true, :global/offboarding [:offboarding/id "DUMMYID"], :root/content {:root/router {::dr/id :app.ui.root/OffboardingIdRouter, [::uism/asm-id :app.ui.root/OffboardingIdRouter] {...}, ::dr/current-route {}, :alt0 {:global/offboarding {:offboarding/id "DUMMYID", ...}, ;; SEE? IT IS HERE! 👇 :offboarding-pages/router {::dr/id :app.ui.root/BaseRouter, [::uism/asm-id :app.ui.root/BaseRouter] {::uism/asm-id :app.ui.root/BaseRouter, ::uism/state-machine-id dr/RouterStateMachine, ::uism/active-state :routed, ::uism/ident-&gt;actor {[::dr/id :app.ui.root/BaseRouter] :router}, ::uism/actor-&gt;ident {:router [::dr/id :app.ui.root/BaseRouter]}, ::uism/actor-&gt;component-name {:router :app.ui.root/BaseRouter}, ::uism/active-timers {}, ::uism/local-storage {:path-segment ["default"], :target [:component/id :home]}}, ::dr/current-route {...}, :alt0 {:info {}}, :alt1 {}}}}}} *Updates* 1. I see in the Root component props that upon the initial render it has the BaseRouter props. But if I `dr/change-route`to a different target of the BaseRouter then suddenly its props aren't there anymore. (This worked 1-2 days ago). But when I run `(let [state (app/current-state SPA)] (denorm/db-&gt;tree (comp/get-query Root) state state))` then the data includes the BaseRouter data, even after it failed to show up in the UI?!!! So the data is there but somehow, when Fulcro fulfills the root query after the routing, it fails to get parts of it?! 2. A key difference between data from `db-&gt;tree` and props of the Root component is that the former includes `[:root/content :root/router ::dr/current-route] {}, [:root/content :root/router :alt0] {:global/offboarding ..., :offboarding-pages/router ...}` while the latter includes `[:root/content :root/router ::dr/current-route] {:global/offboarding ...}` and no`[:root/content :root/router :alt0]`. I.e. the "correct" query has the data under :alt0 while the "wrong" query has them under ::dr/current-route, where it lacks the router data. 3. I am working on replicating the issue on a simpler app created from scratch and failing so far. (I have managed to replicate `::dr/current-route {} and :alt0 {:root/router {..}}`but don't know yet what those are after routing, only that the app works.)

SOLVED: The problem was that I had :will-enter .. (if (data-present app) (dr/route-immediate [:component/id :WRONG]) (dr/route-deferred [:component/id :CORRECT] ..)) i.e. I have used the wrong ident in the if-data-present routing branch. I wish I was better in troubleshooting this...