Fork me on GitHub
#fulcro
<
2020-01-09
>
thosmos09:01:35

I’m watching the videos on UI state machines and it looks like there’s two ways to change to another state:

{::uism/events
 {:event/ok {::uism/target-state :state/idle}
  :event/error {::uism/handler (fn [env] (uism/activate env :state/server-failed))}}}
Is there any difference between these? The book says that: ::uism/target-states is doc, so I’m guessing that entry in the video is just doc … I’ll keep watching as it probably gets explained

thosmos09:01:31

Ah, ok about 20 secs later that got deleted … 😉

tony.kay15:01:24

Those are the two ways to get it to change, yes…the target-states is recommended as a standard for when we have tools to turn the data into a diagram, but it is low on my prio list

jcf15:01:09

Hello everyone! I'm having a quick play with the dynamic router in Fulcro and I've got a couple of questions. 1. How do I change route to "/" ? I can navigate to routes with a path like "/settings" etc. but to go to the home page I'm left scratching my head. 2. There are a bunch of docstrings in the wrong place in the dynamic routing namespace (thank you clj-kondo!). Shall I fix that and open a PR over on GitHub?

jcf15:01:25

I've just opened up https://www.youtube.com/watch?v=oQpmKWBm9HE&amp;list=PLVi9lDx-4C_T7jkihlQflyqGqU4xVtsfi&amp;index=16&amp;t=0s, and I'm watching to make sure the answer isn't in there. 🙂

tony.kay15:01:20

1. Every target needs a non-empty name…you can fix translations between “root” and that single named page in your function that converts URLs to a vector of strings. 2. A PR is fine, thanks…surprised that is the case

jcf15:01:44

I've only moved the docstrings, no formatting etc.

jcf15:01:22

I'm looking into converting the vector of path components and a string path now. 🙂

tony.kay15:01:54

you understood that is something you write, right? (str/split …)

jcf15:01:08

I just need to find out where to provide that. I've cloned the video-series repo and I've checked out the relevant tag to see what your example code does.

jcf15:01:45

Looks like you're using Pushy to hook into HTML5 pushState. I had wrongly assumed the Fulcro router handled that for me I think.

tony.kay16:01:24

right…the router is about the Fulcro-specific details. How you chose (or don’t) to do HTML5 history is up to you

tony.kay16:01:10

I should be clearer on that in the docs. From my perspective routing is an app concern. I provide 3 different implementations, and actively use 2 of them…but even though they are an official part of Fulcro I see routing as something of an external library concern…there are just too many ways ppl want to do it.

jcf16:01:10

I definitely agree with the above. I think the docs just left me assuming Fulcro took on more of the routing concerns than it actually does.

jcf16:01:22

I think the current separation of concerns is sound.

tony.kay15:01:47

got it, thx

4
hadils15:01:37

Ok, I still have the no app connected error when I try to use Fulcro Inspect on my application. I noticed that this application template has the following error:

Uncaught TypeError: Cannot convert a Symbol value to a string
    at Array.join (<anonymous>)
    at Function.eval [as cljs$core$IFn$_invoke$arity$1] (:3001/js/main/cljs-runtime/cljs.core.js:10144)
    at Object.cljs$core$pr_writer_impl [as pr_writer_impl] (:3001/js/main/cljs-runtime/cljs.core.js:33441)
    at Object.cljs$core$pr_writer [as pr_writer] (:3001/js/main/cljs-runtime/cljs.core.js:33472)
    at Object.cljs$core$pr_seq_writer [as pr_seq_writer] (:3001/js/main/cljs-runtime/cljs.core.js:33476)
    at Object.cljs$core$pr_sb_with_opts [as pr_sb_with_opts] (:3001/js/main/cljs-runtime/cljs.core.js:33541)
    at Object.cljs$core$pr_str_with_opts [as pr_str_with_opts] (:3001/js/main/cljs-runtime/cljs.core.js:33555)
    at Function.eval [as cljs$core$IFn$_invoke$arity$variadic] (:3001/js/main/cljs-runtime/cljs.core.js:33638)
    at Object.eval [as rep] (:3001/js/main/cljs-runtime/com.fulcrologic.fulcro.inspect.transit.js:64)
    at Object.writer.marshal (:3001/js/main/cljs-runtime/com.cognitect.transit.impl.writer.js:345)
and I suspect it is preventing Fulcro Inspect from working, since there is nothing else I can find. Any help would be welcomed here...

hadils15:01:31

I am using the fulcro-master-template

tony.kay15:01:51

and the master branch

tony.kay15:01:15

Do you have anything in your .clojure/deps.edn, or any alt location?

tony.kay16:01:20

have you added/removed any dependencies?

hadils16:01:30

I am using http://github.com: fulcro-template-master

tony.kay16:01:43

that is not mine…can’t help you there

tony.kay16:01:55

I run the fulcrologic ns

tony.kay16:01:07

if that isn’t in the prefix, then it isn’t official

hadils16:01:35

Ok. Hold on please.

tony.kay16:01:39

basically, it looks like you’ve broken transit (unfortunately a bit too easy to do on the js side)…typically it is a version mismatch thing

tony.kay16:01:20

Fulcro uses transit to send values to/from the inspect plugin

tony.kay16:01:47

inspect is currently using com.cognitect/transit-cljs {:mvn/version "0.8.256"}

tony.kay16:01:33

it is possible you’re getting a version that is incompatible.

hadils16:01:52

I will use your official template.

hadils16:01:16

@tony.kay Let me fix my transit-cljs and let you know.

hadils16:01:35

Here's my deps.edn:

{:paths   ["src/main" "resources"]

 :deps    {org.clojure/clojure                 {:mvn/version "1.10.1"}
           bidi                                {:mvn/version "2.1.6"}
           bk/ring-gzip                        {:mvn/version "0.3.0"}
           com.taoensso/timbre                 {:mvn/version "4.10.0"}
           com.taoensso/tufte                  {:mvn/version "2.1.0-RC4"}
           com.wsscode/pathom                  {:mvn/version "2.2.26"}
           com.fulcrologic/fulcro              {:mvn/version "3.1.2"}
           com.fulcrologic/fulcro-garden-css   {:mvn/version "3.0.7"}
           com.fulcrologic/semantic-ui-wrapper {:mvn/version "1.0.0"}
           com.fulcrologic/guardrails          {:mvn/version "0.0.9"}
           http-kit                            {:mvn/version "2.3.0"}
           mount                               {:mvn/version "0.1.12"}
           org.clojure/core.async              {:mvn/version "0.4.500"}
           tick                                {:mvn/version "0.4.21-alpha"}
           hiccup                              {:mvn/version "1.0.5"}

           ;; To simulate Datomic on the back-end
           datascript                          {:mvn/version "0.18.4"}

           ring/ring-core                      {:mvn/version "1.7.1"}
           ring/ring-defaults                  {:mvn/version "0.3.2"}
           kibu/pushy                          {:mvn/version "0.3.8"}}

 :aliases {:clj-tests {:extra-paths ["src/test"]
                       :main-opts   ["-m" "kaocha.runner"]
                       :extra-deps  {lambdaisland/kaocha {:mvn/version "0.0-554"}}}

           :dev       {:extra-paths ["src/test" "src/dev" "src/workspaces"]
                       :jvm-opts    ["-XX:-OmitStackTraceInFastThrow"]
                       :extra-deps  {org.clojure/clojurescript   {:mvn/version "1.10.520"}
                                     thheller/shadow-cljs        {:mvn/version "2.8.58"}
                                     expound                     {:mvn/version "0.7.2"}
                                     fulcrologic/fulcro-spec     {:mvn/version "3.1.4"}
                                     binaryage/devtools          {:mvn/version "0.9.10"}
                                     nubank/workspaces           {:mvn/version "1.0.13"}
                                     gnl/ghostwheel              {:mvn/version "0.3.9"}
                                     org.clojure/tools.namespace {:mvn/version "0.3.1"}}}}}

thheller16:01:27

@hadilsabbagh18 the error comes from trying to print a js/Symbol (which all react elements use). what are you trying to print/write?

thheller16:01:56

might happen if you put react elements into the app db and fulcro inspect tries to send it elsewhere

hadils16:01:31

I think that is the problem @thheller. I have react fragments in my client db. I will try to correct this...

tony.kay16:01:41

clj -Stree is more useful

tony.kay16:01:33

And also what @thheller said: If you put a React class (or any function) into the state db then you are asking for trouble

tony.kay16:01:35

I’m guessing this code in Fulcro:

(deftype DefaultHandler []
  Object
  (tag [this v] "unknown")
  (rep [this v] (pr-str v)))
is the culprit

thheller16:01:09

there is a snippet somewhere to make symbol printable

tony.kay16:01:11

I’ll wrap that with exception handling, and that should fix it

thheller16:01:25

basically just extending the protocol onto js/Symbol

tony.kay16:01:29

well, in general, this function gets called for ANY non-transit compatible value

tony.kay16:01:40

so it should be more bomb-proof

thheller16:01:40

but yeah unlikely you'll be able to "restore" it anways

jcf16:01:46

From http://book.fulcrologic.com/#_initial_route: > If you are doing SSR, then you will need to simulate calling `change-route` there. The function `dr/ssr-initial-state` (written, but untested) can be used to help you construct the proper state for a given path (which must be used for the server-side render, and also as the initial state for the client). Technically, this means that the function can also be used to generate initial state for the client on the front-end as well. I need SSR support for this service I'm planning on building, and have initial state being reset into my Fulcro DB (albeit using a slightly different impl.). I can't find any ssr-initial-state var in the Fulcro codebase, and the contents on change-route are formidable. Am I looking in the wrong place, or maybe the function is called something else?

tony.kay16:01:57

@hadilsabbagh18 Try Fulcro version 3.1.3-SNAPSHOT

tony.kay16:01:30

I added exception handling at that point…the value in question should show up in the DB viewer in inspect as UNENCODED VALUE now, instead of breaking it

tony.kay16:01:46

@jcf server-render ns…I think fn changed names…

tony.kay16:01:54

build-initial-state

tony.kay16:01:00

But that just does the steps for setting up the base initial state. If you’re using dynamic router you’re probably going to have to create a headless Fulcro client on your server, and trigger the routing against that, and then dump the state atom from it as the client initial db

jcf16:01:20

Okay, I'm in the right ballpark in that case. I've gotten as far as this on the server:

(defn- markup
  [initial-state rendered]
  [:html {:lang "en"}
   [:head
    [:meta {:charset "utf-8"}]
    [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
    [:script {:type "text/transit+json" :id "initial-state"}
     (html/->RawString (html/write-transit-string initial-state))]
    [:title "Top Secret!"]]
   [:body
    [:div#app (html/introduce-danger rendered)]
    [:script {:type "text/javascript" :src "/js/main.js"}
     "secret.client.hydrate()"]]])

(defn render-client
  [_request]
  (let [normalized-db (algo.ssr/build-initial-state {} root/Root)
        props (algo.denorm/db->tree (comp/get-query root/Root)
                                    root/Root
                                    normalized-db)
        root (comp/factory root/Root)
        app (app/fulcro-app {})]
    (binding [comp/*app* app]
      {:status 200
       :body (str ""
                  (rum/render-static-markup
                   (markup normalized-db (dom/render-to-str (root props)))))})))

tony.kay16:01:23

I don’t use SSR, and no one has made the time for V3 to work out the kinks

jcf16:01:35

I guess I'll be that person then! 🙂

tony.kay16:01:37

I’ve run the app headless in JVM for demo purposes…but there are likely to be some rough edges there

jcf16:01:10

I've gotten SSR working with Rum previously using almost the same approach as what's in Fulcro. I didn't base64 encode my Transit payload though; I liked that a lot.

tony.kay16:01:46

without that you get some transit encodings that are not properly quoteable in js

jcf16:01:59

I did notice rendering to a string causes one problem. React doesn't want the data-reactid in the HTML string. Rum has a separate function to get around that.

tony.kay16:01:34

I think v15 did want that, and no one has taken the time to port it forward.

jcf16:01:32

I use a dedicated script tag with a type of text/transit+json . As long as there's no unescaped HTML in there I think that's okay.

jcf16:01:24

Porting that should be quite easy. I'll add it to my todo list. 🙂

tony.kay16:01:31

@jcf Thanks…happy for PRs on that…be nice to know that is polished and working…updates to book are also welcome, as is a new branch on the template showing a basic app doing it.

👍 4
hadils16:01:40

I haven't tried it yet. I was refactoring my initial-state to get rid of React fragments. I have a pure database now. Thanks for your help, @tony.kay!

tony.kay16:01:59

ah, would be interested in it working (testing it) even WITH bad stuff in db 🙂

🙂 4
tony.kay16:01:34

would prevent future problems/questions on the channel 😉

hadils16:01:12

@tony.kay I will test it and let you know...

hadils16:01:21

Ok. I've made my changes which do not affect workspaces. I brought workspaces and am still getting no app connected.

tony.kay17:01:06

That was word salad 😉

hadils16:01:02

@tony.kay @thheller. Fulcro inspect now works with my app. There's something I did inside workspaces that needs to be fixed. Thank you both for your efforts to help me!

tony.kay17:01:49

OK, so you’re saying that with your screwy app state and 3.1.3 that inspect is fine now?

jcf17:01:14

I think I'm going to call it a day. I can't seem to convince the dynamic router to update my app state using this code, and a fresh brain is probably what's required to make progress.

(defn render-client
  [_request]
  (let [normalized-db (algo.ssr/build-initial-state {} root/Root)
        props         (algo.denorm/db->tree (comp/get-query root/Root)
                                            root/Root
                                            normalized-db)
        ui-root       (comp/factory root/Root)
        root          (ui-root props)
        app           (app/fulcro-app {})
        _             (app/set-root! app root/Root {:initialize-state? true})
        _             (fulcro.routing/change-route-relative app root ["settings"])]
    (log/debug :in ::render-client :app-state @(::app/state-atom app))
    (binding [comp/*app* app]
      {:status 200
       :body   (str ""
                    (rum/render-static-markup
                     (markup normalized-db (dom/render-to-str root))))})))
I think I'm passing the right things around there but all the apps and roots are merging together at this point. 😄

tony.kay17:01:26

I think you should probably start the app WITHOUT using build-initial-state, and use db->tree on the real app state for generating the SSR @jcf

👌 4
jcf17:01:17

@tony.kay I would kill for an example. 🙂

jcf17:01:34

Let me see what I can muster before I go and make myself an old fashioned.

tony.kay17:01:32

1. Make the app 2. Run initialize-state! in app ns and trigger any actions that you need to initialize your own app 3. Run mutations on the app (e.g. change route, begin state machines, etc.) 4. Pull the app state, and use db->tree just like you already are, to make props for root

jcf18:01:56

Trying this now. Thank you, @tony.kay!