Fork me on GitHub
#fulcro
<
2019-04-01
>
mitchelkuijpers16:04:28

I am fighting with Intellij and fulcro.incubator.dynamic-routing and then the defsc-route-target for some reason intellij does not want to resolve it. Anyone here ran into the same issue?

adamfeldman16:04:09

I haven't used Intellij in a long time, but this may be helpful if you aren't familiar already: https://cursive-ide.com/userguide/macros.html (and if you are already familiar -- https://github.com/cursive-ide/cursive/issues/1505#issuecomment-319307955)

mitchelkuijpers16:04:57

Thank you I am familiar, and these are not the issues unfortunately 😞

tony.kay16:04:09

@mitchelkuijpers you have to go into incubator and resolve defsc-extended

mitchelkuijpers16:04:18

Fixed it by first adding a resolve-as for defextened-defsc and the resolving

tony.kay16:04:21

I believe as defmacro

mitchelkuijpers16:04:28

lol had just figured it out

tony.kay16:04:30

yeah, that 🙂

mitchelkuijpers16:04:43

I resolved it as def

tony.kay16:04:44

same for specter and other libs that have macros making macros

tony.kay16:04:15

let me know how the dynamic router goes for you…we’re loving it on the projects I’m using it on

mitchelkuijpers16:04:24

would be very cool if libs could hint cursive about resolving stuff

mitchelkuijpers16:04:43

We are already using it, but this is the first I am gonna try it out

wilkerlucio16:04:48

yeah, maybe it could read from metadata

mitchelkuijpers16:04:03

Or a simple xml file in the jar or something

tony.kay16:04:23

did you just suggest XML? 😜

😅 4
mitchelkuijpers16:04:47

More because cursive is already using it 😛

mitchelkuijpers16:04:57

But yeah metadata would be cool

tony.kay17:04:27

Fulcro 2.8.8 adds a (long overdue) global component registry: http://book.fulcrologic.com/#_the_component_registry_version_2_8_8

👍 4
hmaurer17:04:02

> tracking classes (by name) in app state (which cannot appear there as “code”). do you have an example use-case for this @tony.kay?

tony.kay18:04:52

I’m adding one to incubator now: UI state machines need to track the component class of an actor. I was doing that via metadata on the idents; however, Inspect doesn’t get this metadata, so if you restore a snapshot of app state the state machine stops working. With a registry, I can simply store the FQ names of the classes in app state. Things end up more visible to the user, and inspect works properly. Another use-case would be a mutation that needs to refer to a component for a data merge, where you’d also like to require that mutation ns with the UI code (for aliasing convenience). Doing so in both directions would create a circular ref. You can fix this latter one by simply typing out the long name, but this gives you the option of typing the long name in the mutation instead of in every mutation call site.

wilkerlucio18:04:44

that's a good point to send/store the metadata as well, we can make this available on inspect

tony.kay18:04:46

we need to be careful @U066U8JQJ …the metadata is mainly used to store non-serializable stuff

tony.kay18:04:58

so “sending” it to inspect has the same problems

wilkerlucio18:04:22

yeah, true, is there something other than the components that is not serializable and goes there?

tony.kay18:04:38

I use it for things like js File objects for file uploads, and things like that

tony.kay18:04:10

also, dynamic queries go in app state, and they need metadata to point to the classes…I still need to patch that to use the new registry instead

wilkerlucio18:04:04

yeah, I'm thinking it can be useful even if it's not complete

wilkerlucio18:04:25

and maybe we can have a custom encoder for components, that could send relevant information about it (just the name would be useful already)

tony.kay18:04:05

yeah, but without the registry snapshots still would not work

wilkerlucio19:04:09

makes sense, I was thinking about the usefulness of having the meta data in inspect as well, but agreed its not enough to fix the snapshot

tony.kay18:04:24

Code splitting is another one: When you load code, you need to be able to look up the loaded component

tony.kay18:04:55

you cannot refer to it in the base program directly, so you need someplace that it can “register itself”…I was leaving this to ad-hoc implementation, but now the registry can serve as that location

mitchelkuijpers19:04:55

I am fighting with dynamic routing for some reason my deferred never seems to resolve

mitchelkuijpers19:04:34

:will-enter (fn [reconciler {:keys [issue-id] :as props}]
                 (when-let [issue-id (some-> issue-id (js/parseInt))]
                   (let [ident [:my/ident issue-id]]
                     (dr/route-deferred ident
                                        #(do
                                           (js/console.log (str "loading " ident))
                                           (prim/transact! reconciler `[(kit-utils/load-templates)])
                                           (df/load
                                            reconciler
                                            ident
                                            Issue
                                            {:marker false
                                             :abort-id :issue-load
                                             :initialize true
                                             :post-mutation `dr/target-ready
                                             :post-mutation-params {:target ident}}))))))

mdhaney19:04:22

@mitchelkuijpers does your ident for the route target match? other than that, I don't see anything that jumps out as wrong.

mitchelkuijpers19:04:01

Yes that one is the same

mdhaney19:04:58

Only other thing I can think of - if you have previously called route-deferred and never resolved it, that seems to mess up the state machine. I ran into this one time - when something fails, you generally want to redirect to another page (show an error, etc.

mdhaney19:04:16

but if you do that without resolving the failed route first, it messes things up.

tony.kay19:04:45

@mdhaney sounds like a bug that should be fixed

tony.kay19:04:12

perhaps…not sure. I mean if you say you’re deferring and then fail to do so, I’m not sure who “owns” that

mdhaney19:04:49

@tony.kay yeah, I wasn't sure if that was how it was designed or not.

tony.kay19:04:00

but seems like d.r. could stop paying attn and just deal with the new one

tony.kay19:04:25

don’t remember. You can certainly start a new route while one is waiting to defer

tony.kay19:04:44

at least that is how it is designed…user route changes could come at any time

tony.kay19:04:22

@mitchelkuijpers a when-let isn’t a good idea

tony.kay19:04:37

well, actually might be ok there

mitchelkuijpers19:04:48

Ah I copied it from the docs 😛

tony.kay19:04:01

I was reading the nesting wrong

mdhaney19:04:01

I don't remember the exact failure. It happened when I first switch to DR, and I realized if I call target-ready on the old route right before I switch routes, it fixed it.

tony.kay19:04:18

then that sounds like a bug

mitchelkuijpers19:04:33

Might this be a problem?

mitchelkuijpers19:04:49

(defrouter LinkingPanelRouter [this {:keys [current-state]}]
  {:router-targets [Issue]}
  (case current-state
    :initial (dom/div "What to show when the router is on screen but has never been asked to route")
    :pending (ui-loader)
    :failed (dom/div "Oops")
    (dom/div "No route selected.")))

mitchelkuijpers19:04:12

The first router target needs a ident, but it seems to load it for one second without the correct ident

mdhaney19:04:05

@tony.kay since we're on the subject of DR, here's another one I just ran into Friday. I have nested routers and I route to the child one, and that route target is depending on data that should be loaded in the parent router. What I was expecting is that it would resolve the deferred route on the parent router before trying to route to the child, but that was not the case. I put in logging statements to confirm, and sure enough it calls will-enter on the parent, starts the load, then calls will-enter on the child, then the load finishes and calls target-ready on the parent. Not sure if that's intended behavior or a bug.

souenzzo19:04:53

How do I handle network errors? http://book.fulcrologic.com/#_detecting_errors_from_the_server docs says about deprecated :network-error-callback and I'm using a "custom" fulcro-http-remote Should I do something l do something like it {:response-middleware (-> (fcn/wrap-fulcro-response) (network-error error-chan))} ?

mdhaney20:04:20

@souenzzo that seems reasonable. For global errors, you generally want to log and maybe set something in app state that triggers a message in your UI (for instance, offline message for a mobile app that loses network). Then for handling errors in specific situations, I.e. where you know about the context and can take action, use the fallback mutation on your load.

souenzzo20:04:45

I want to do something like "case 403 -> [(app/logout {})]

tony.kay20:04:55

You can do that with middleware, to a point. Well, technically with middleware all the way.

tony.kay20:04:56

so, the middleware can rewrite the “query” and the “response”…so, you could change the query to one that would overwrite the “session info” that the login is based upon, and “make up” the tree of data.

tony.kay20:04:04

that works as long as all you need is a state change with a refresh. You can also put the reconciler in a well-known atom and use that as a bit of a “hammer” for these kinds of circumstances…i.e. transact a new thing against the reconciler.

tony.kay20:04:08

The websockets support has a hook that calls a functoin when network status changes, and typically the thing you provide does just those kinds of transactions.

mitchelkuijpers20:04:21

My problem was that I did not call get-initial-state on my LinkingPanelRouter now it works like a charm

👍 4
tony.kay20:04:59

Note to @mitchelkuijpers and @mdhaney there is a known issue with dynamic router and state machines…really it is a design weakness in Fulcro: the dynamic router and state machine combo requires transactions that end up running is a hard-to-define (and see) order. There is a lot of setTimeout magic going on to prevent actual transactions from running truly “nested”, but that leads to conditions where the scheduling of setTimeouts happen “out of desired order”, leading to strange bugs. I’ve written an issue and RFC about this… That said, I’m using them pretty heavily with no complaints. On the “nested” deferred stuff. A route instruction will process all the way to the end (i.e. all routers in the target path will be told “will enter”). Any number of them can defer. Actual route display happens based on the state machine resolution of the actual paths. Technically a child could “finish” its routing before a parent…not that it would be on screen until the parent finished.

mdhaney20:04:53

Makes sense. I was just making an unwarranted assumption about the ordering of route resolution, which is what I suspected but just wanted to clarify. Thanks!

tony.kay20:04:08

yeah, there is no real need to force a sequential evaluation that I can see, so every router on the target path is told it will enter, and they can all defer in parallel.

tony.kay20:04:37

order of results don’t matter either, since things are rendered top-down…

tony.kay21:04:52

@mdhaney perhaps your use-case is the more correct way, though. You state “the child depends on state the parent is loading”. Unfortunately I can see valid cases in both directions (parallel eval vs waiting to route the child). This is yet another use-case that would be solved by the new priority queue stuff I’ve written that RFC for: https://github.com/fulcrologic/fulcro/blob/feature/react-play/docs/RFCs/RFC-transaction-semantics.adoc With that support you’d be able to indicate that the child’s transaction doesn’t even start until the parent’s completes.

tony.kay21:04:38

I don’t have the motivation/time to change how d.r. is doing it, but I hope to start on the Fulcro 3 advances soon.

tony.kay21:04:43

Incubator 0.0.32 released to clojars. Requires Fulcro 2.8.8. Fixed UI state machines to use the component registry, which makes them behave properly when using the database snapshot feature of Inspect

🎉 36
💯 4
❤️ 4