Fork me on GitHub
#fulcro
<
2021-04-12
>
Andreas Edvardsson11:04:23

Do anyone have any ideas on how to implement pretty urls with the dynamic router? Let’s say I have a route /user/andreas where andreas isn’t the users actual id, but some other unique identifier. If I’m just creating a component with :route-segment ["user" :user-alias] and then utilising a load! in route-deferred, I have the problem that I have no way of knowing the actual id (and thus ident) of the user beforehand. Just passing [:user/alias user-alias] as the ident to route-deferred triggers an error message. I guess I could try to resolve the alias into an id first, and then trigger the route-change to a component having :route-segment ["user" :user-id] , which will then query the server for the info it needs, but then I have to fire two separate requests to the server.

Andreas Edvardsson11:04:28

Maybe I should just trigger the load for the user separately with the alias as an parameter and then, when the data is loaded, trigger the route change, not loading anything in the :will-enter fn

dvingo14:04:06

I think you'd likely need a component that uses the user alias in its ident in order for the router to not throw the error you mentioned. Then also have the server allow taking the alias as an ID when queries are issued (because on first load the client will not know this mapping) and then have an index table in the fulcro client db user-alias -> [:user/id <id>] This way you can keep using :user/id as the ident in all your other components and in the refs to users.

👍 3
dvingo14:04:45

Your second comment might also work - I had to do something similar when my URL didn't match my fulcro-segment - will-enter always calls route-immediate and then I issue the load in compDidMount and render the appropriate UI in render (loading, showing cached data etc).

Jakub Holý (HolyJak)14:04:26

I agree, I't make the target component use the alias in its ident + :route-segment ["user" :user-alias] and model it as an entity with a single field, {:user-alias/data <data>} . . Then use perhaps a post-load mutation to move the user data into -> client-db :user/id <id> and replace its origin with an ident: -> client-db :user/alias <alias> :user-alias/data = [:user/id <id>]

Andreas Edvardsson15:04:24

Thanks for the suggestions! I also like the first suggestion with the component having the alias as an ident, since it plays along nicely with the routing out-of-the box. However, when if I instead have a pair of attributes which together indentify an entity, say a GitHub inspired example with username and repo name combination /user/andreas/repo/hello-world this solution doesn’t seem optimal since one’s need to create a ident with :user/alias+repo-name and make the server understand that. Also, that leaves a lot of duplicate aliases and the like all over the state.

Jakub Holý (HolyJak)15:04:38

I do not really see the difference between [:user/alias "andreas"] and [:git/repo ["my user" "my repo"]]

Andreas Edvardsson15:04:36

That’s true, I didn’t think of using vectors as ids, I’ll give that a shoot!

thosmos18:04:49

I just started getting a shadow-cljs build error on a fulcro dep after updating from git. I tried switching back to the latest maven deps but I’m still getting it. Not sure what’s causing it.

Build Status
X Compilation failed.
------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/thomas/.m2/repository/com/fulcrologic/guardrails/1.1.4/guardrails-1.1.4.jar!/com/fulcrologic/guardrails/core.cljc
failed to require macro-ns "com.fulcrologic.guardrails.core", it was required by "com.fulcrologic.guardrails.core"
Error in phase :compile-syntax-check
RuntimeException: No such var: printer/highlighted-value
Downgrading from fulcro-rad-datomic from 1.0.7 to 1.0.5 fixed it

tony.kay23:04:06

@U0CSAHDV0 ring any bells? Did we do something to GR with respect to highlight?

adambrosio23:04:23

it does not…

tony.kay00:04:46

@U07KXN95L possibly expound version???

tvaughan19:04:43

In section https://book.fulcrologic.com/#_building_the_app_state_on_the_server I see (*let* [base-state (ssr/build-initial-state (my-app/get-initial-state) my-app/Root) however I don't see an explanation of my-app/get-initial-state. This is the only occurrence of get-initial-state that isn't under the comp namespace. This looks like a function I need to create, but what should it return? Or is this a typo?

tony.kay23:04:15

Right. The initial state is typically the tree generated from get initial on Root, with any addl stuff you might want to throw in.

👍 3
tvaughan19:04:01

In section https://book.fulcrologic.com/#_rendering_with_initial_state I see (*let* [props (fdn/db->tree (comp/get-query app/Root normalized-db) state-map state-map) however I'm unsure how to create normalized-db. I think I understand what state-map should look like and how it's created. Searching through the fulcro and fulcro-template repos doesn't turn up an example. Is there a complete, working example of how to set up server-side rendering somewhere?

tvaughan20:04:44

For completeness, here's what I have and it appears to be working:

(defn- compute-context
  [request target]
  (let [session-state (merge (parsers/sessions-endpoint (get-query sessions/Session)
                                                        {:target [:component/id :session]
                                                         :remote :sessions
                                                         :request request})
                             {:session/next-uri (:uri request)})
        session-ident (get-ident sessions/Session session-state)
        server-side-state (-> (ssr/build-initial-state (get-initial-state ui/Root) ui/Root)
                              (assoc-in (conj [::dr/id ::ui/SiteRouter] ::dr/current-route)
                                        (get-initial-state target))
                              (set-query*
                                ui/SiteRouter {:query [::dr/id {::dr/current-route (get-query target)}]})
                              (assoc :sessions/session session-ident)
                              (assoc-in session-ident session-state))
        server-side-app (application/fulcro-app {:initial-db server-side-state})
        ;; TODO: Per ,
        ;; what is `normalized-db` and is it required? See also:
        ;; 
        server-side-props (denorm/db->tree (get-query ui/Root #_normalized-db) server-side-state server-side-state)
        content (binding [*app* server-side-app]
                  (dom/render-to-str (ui/ui-root server-side-props)))
        script-tag (ssr/initial-state->script-tag server-side-state)]
    {:content content
     :script-tag script-tag}))

tvaughan20:04:19

On the client-side:

(defn ^:export init!
  []
  (let [initial-state (get-SSR-initial-state)]
    (reset! (::fapp/state-atom app) initial-state))
  (mount! app ui/Root "app" {:hydrate? true :intialize-state? false})
  (uism/begin! app sessions/state-machine :sessions/state-machine
               {:actor/session sessions/Session
                :actor/create-session sessions/SignIn})
  (hist/init! app)
  (messages/enable-messages!)
  (js/console.log "Fulcro app has been initialized"))

tvaughan20:04:30

As Tony said, my problems in https://clojurians.slack.com/archives/C68M60S4F/p1617992612455400 do appear to be because initial state was incorrect

tvaughan21:04:26

> and it appears to be working Sorry, my mistake. Works for some routes, not others.

tony.kay23:04:39

normalized-db is the same thing as state-map

tony.kay23:04:42

sorry for the confusion

tvaughan11:04:01

Cool. Thanks for the clarification @U0CKQ19AQ

hadils20:04:59

How do I create a ref for a component in a third-party library in Fulcro? I am using react-factory because it's a React Native app and I see a nil :ref field in the resulting object.

tony.kay23:04:02

standard React fare there…nothing really to do with Fulcro (react-factory just passes along your stuff to React). Not sure how refs work in Native land

hadils23:04:48

Thank you Tony