Fork me on GitHub
#fulcro
<
2018-10-08
>
magra09:10:16

My old mutations including tempids work correctly. Now I followed the developers guides to implement form state. The GUI seems to work fine and optimistic update with tempids seems to work as before. But fulcro-inspect stops updating. The return message from the server with the tempids ist the last thing that gets updated in inspect. The app itself keeps working. When I kill the Devtools and restart them the db looks good, as far as I can see. Has anyone seen this?

kirill.salykin09:10:46

hi all is there a official way to support nested hashmaps in query/form state? Should i somehow normalize it myself? I have normalized entity which stored in :entity/by-id. This works just fine But entity have the m field which is hashmap. How can tell fulcro to normalize and handle it as well?

entity/by-id id {:name "Entity" :m {:something "foobar :else "barfoo"}}

kirill.salykin09:10:05

seems like fulcro handles nesting automagically

wilkerlucio12:10:44

@kirill.salykin it does handle nesting automatically, the db->tree function handles that, but I suggest you try to normalize everything, get this item, create a component, make an ident and a query so fulcro will normalize for you, on the long run this will make your components easier to work with (dealing with nesting in mutation is never fun, dealing with flat things scales much better)

kirill.salykin12:10:33

@wilkerlucio thanks!

wilkerlucio12:10:31

@kirill.salykin no worries 🙂 and in the case of to-one relationships (which usually manifest as a map value), try to think if you cant use namespaced keywords and turn it into a flat thing, for example, instead of {:name "Walter" :address {:street "First Av"}}, you can try going for {:user/name "Walter" :address/street "First Av"}

kirill.salykin12:10:40

not sure it is applicable in my scenario, but thanks for advice

wilkerlucio12:10:36

sure, whatever makes sense

kardan12:10:10

I think I remember reading a blog post about Hiccup style v.s. function based “React” markup. Can’t find it now. Anyone who knows what I’m talking about?

eoliphant19:10:21

hi, what's the fulcro'y way to handle 'out of band' API calls? For instance, my UI needs to say, call Auth0/Cognito/etc. via their respective client lib. Right now, I'm generally just firing off a mutation based on the response callback,

tony.kay20:10:38

@eoliphant I’ve done it a number of different ways, depending on the API. If it is a js API, then yeah, you’re calling functions, and they are doing the rest…so embedding in mutations is a decent idea since you can update your own UI as needed that way. If it is some kind of network API, then my current favorite approach is to make a Pathom remote with a client-side async parser, and satisfy queries via Connect resolvers that directly call things like http-client get. Then you can use the load API with targeting and such.

tony.kay20:10:31

(ns rest-remote
  (:require [com.wsscode.pathom.connect :as pc]
            [com.wsscode.pathom.core :as p]
            [com.wsscode.pathom.fulcro.network :as pn]))

(defmulti resolver-fn pc/resolver-dispatch)
(defonce indexes (atom {}))
(defonce defresolver (pc/resolver-factory resolver-fn indexes))

(defn rest-parser
  [app-atom]
  (p/async-parser
    {::p/plugins [(p/env-plugin
                    {::p/reader             [p/map-reader
                                             pc/all-async-readers]
                     :app-atom              app-atom
                     ::pc/resolver-dispatch resolver-fn
                     ::pc/indexes           @indexes})
                  p/request-cache-plugin]}))
(defn rest-remote
  [app-atom]
  (pn/pathom-remote (rest-parser app-atom)))

...

(reset! app (fc/new-fulcro-client
                :networking {:rest       (rr/rest-remote app)
...

tony.kay20:10:08

Then you can use defresolver to make resolvers for keywords, and use them via:

(df/load this :api-keyword nil {:remote :rest ...})

tony.kay20:10:18

A resolver might look like this:

(defresolver `some-api-name
  {::pc/output [:some-value]}
  (fn [{:keys [ast]} _]
    (async/go
      (let [params (-> ast :params)
             result (some-async-call params)]
        {:some-value result}))))

tony.kay20:10:37

and you can pass the params in via load’s :param option, and use post-mutations, targeting, etc.

eoliphant22:10:36

THanks @tony.kay "is to make a Pathom remote with a client-side async parser, and satisfy queries via Connect resolvers that directly " sounds like some extra work but would keep the client super clean