Fork me on GitHub
#fulcro
<
2018-09-16
>
pvillegas1200:09:19

I got rid of the error but now I get a warning [ 3.037s] [fulcro.client.primitives] component contaico.ui.root/IntegrationRouter-Union’s ident ([:integration/by-id nil]) has a nil second element. This warning can be safely ignored if that is intended. , a nil instead of the actual value.

cjmurphy00:09:29

@pvillegas12 That's when the props going into your component are not complete, can even mean nil for the whole props - but obviously it is nil for whatever the id is, just as it says. If you can't actually see the problem by looking in Fulcro Inspect, and your application works perfectly, then this message can perhaps be ignored - because it is referring to a temporary situation that has since corrected itself.

pvillegas1200:09:22

this goog.math.Long is annoying getting converted, somewhere in the routing code it is getting converted to a number and dropping the last digit 😞

pvillegas1200:09:42

I managed to extend the bidi protocol to convert it into a string, but it’s being coerced somewhere else

pvillegas1200:09:19

With datomic, what is normally the course of action to deal with the :db/id?

cjmurphy00:09:22

Normally the :db/id from Datomic finds its way into your client state and there are no problems.

pvillegas1200:09:53

The problem right now is that 44143192831950917 is too large

pvillegas1200:09:14

(the datomic generated ids, so they are being coerced by goog)

pvillegas1201:09:58

@tony.kay transit it sending ~i46157498134036548 which is a 64 signed integer. However, the :fulcro.client.routing.routers/by-id value in the database is pointing to 46157498134036540. I suspect there is a bug with coercing this 64 signed integers somewhere in the defrouter

tony.kay01:09:53

That is extensible as well if you keep reading…you can customize how it coerce’s bidi parameters

tony.kay01:09:05

that is coerce-param in fulcro.client.routing

pvillegas1212:09:44

Got it to work, thanks! Thank you for making that extension point 😉

tony.kay01:09:09

which is a multimethod

pvillegas1201:09:53

@tony.kay how I would I extend it?

pvillegas1201:09:12

ah, nvm, :default is called in case it does not pattern match 🙂

pvillegas1216:09:48

How can I load data for a given route without using the started-callback function with fc/new-fulcro-client

claudiu17:09:15

@pvillegas12 What is the use-case ?

pvillegas1217:09:03

I want to load a list of models when I hit the /list route. Once I navigate to the details, I want to load the given model as well. If I hit the details of the model /list/id I want to only load the model

pvillegas1217:09:16

@claudiu it’s mainly a question of, when I enter a route using defrouter what is the canonical place where I can fire a load action and have a ui marker in place to wait for data from the server to come back?

claudiu17:09:09

Think the most common place for that is in the mutation for changing the route.

pvillegas1217:09:19

ah I see, at that point I can decide to load depending on the current state of the db

pvillegas1218:09:29

@claudiu This works when you call the route mutation from your UI, what do you do when the user is going directly to a specific URL?

pvillegas1218:09:12

One option would be to conditionally fire a load action in the r/route-to function itself depending on the handler supplied

pvillegas1218:09:45

Without that, it would not fire the load correctly as it won’t fire the mutation (which is normally fired when a user clicks on a button)

claudiu18:09:36

what do you mean by going directly to a specific url, the first time the user loads the app ?

pvillegas1218:09:01

or refreshing a details URL such as /model/id

claudiu18:09:20

I usually have ssr, so I get the route data from the server in the app-state. But think for initial entry point, it's the started-callback that has to fire the right df/load or mutation for the route.

pvillegas1218:09:35

Right, but started-callback is an app-level loading, I would not want to fire the load action for a model in a the /models URL

claudiu18:09:16

started-callback will fire only once when you enter the app. There you load the current user and app-level stuff like that, but you could also load the data for current route.

claudiu18:09:28

worth checking out the fulcro-template and how it has html5 & routing.

pvillegas1219:09:57

Yeah, I’ve looked at it @claudiu trying to get a feel of what architecturally is better.

pvillegas1219:09:58

Currently, it seems that I would have to write ensure-* mutations everywhere where I change routes when I use the html5 routing

pvillegas1219:09:04

Referencing the fulcro template, I would have to do '[(nav-to route-name) (ensure-model-loaded route-name)] everywhere where I want to change routes

pvillegas1219:09:36

I could perhaps wrap it too, but I would still need to handle the initial state as you mention

claudiu19:09:22

plenty of flexibility, not much in fulcro getting in the way. Currently I'm experimenting with load data for routes co-located on the page component. Got it working pretty nicely but still very drafty stuff code wise.

pvillegas1219:09:53

What is the API to pass down data through props for defrouter? I want all components to receive a handle to the ui/loading-data root level attribute

claudiu19:09:21

think you have to add them to the component query :query [ [:ui/loading-data] '_]

pvillegas1219:09:26

I want to avoid the root-level query by “passing it down” through props

pvillegas1219:09:36

but I need to pass it through a defrouter definition

claudiu20:09:30

if you need it in a lot of components maybe :shared http://book.fulcrologic.com/#_useful_reconciler_options (haven't used it yet)

claudiu20:09:04

not sure it's for loading markers though 🙂

claudiu20:09:25

not sure you can pass it from defrouter, but there the top component that the router is rendering , you can add it to the query there and just pass it via computed to the children that need the info.

tony.kay20:09:09

Unfortunately :shared only updates if you force a refresh of the root query (e.g. you'd have to query for :ui/loading-data on root, AND put it in follow-on reads...which would cause a root prop re-query for each refresh. The link query first suggested it probably best for that one, though I'd use load markers instead for localized loading rendering.

tony.kay20:09:51

Note that loading-data AND load markers are for loads. Neither gives indications for mutations. For mutations, you generally use ptransact, set a flag of your own on start, and then have one of the mutations (after the network one) switch the flag back. Wilker has thrown some stuff in fulcro-incubator around extending the mutation system to deal with this common pattern.

tony.kay20:09:45

defpmutation

tony.kay20:09:47

It is entity-centric (e.g. it uses the ref prop of mutation env to figure out which entity to mess with in state for its extra ops)

claudiu19:09:30

@tony.kay Got ssr working on nodejs: transact! seems to work out of the box, but for df/load (xhrio seems to be browser only) I made a custom network and changed xhrio with axios. Right now it works because I added a dummy timeout. Any tips on what would be a elegant way to approach the "when data finished loading" ?

claudiu20:09:26

My first thought would be to delay the response, and add an watcher to the app-state. And just check on every event the markers in the app-db, once loads are completed just resolve the request. Not sure it's the most elegant solution though.

tony.kay20:09:01

@claudiu core.async comes to mind

tony.kay20:09:04

Remember that load, by default, serializes requests. That means that the post-mutation of the last one will run, well, last 🙂 So, you could put your logic in a post-mutation of the last load that triggers your "done"...an async chan might be a nice way to coordinate on that

tony.kay20:09:10

Be great to see a blog post or something related to what you did.

claudiu06:09:43

@tony.kay I'm working on a small "toy project" for the clojure community. Hopefully it will be something usefull, but the main goal is to have a fulcro "production app" that I can open-source (ssr, nodejs, graphql, routing, , and a few crazy ideas). Still early draft stages as soon as I have something working and decent code will make the repo public.

claudiu06:09:26

For ssr & my router idea, would help if I had something like: "as soon as the network queue is empty call this function, then forget about it". Don't know if it can be in fulcro core.

tony.kay14:09:04

Hm. I'll think on it. The real network queue is deep in the bowels. I'll think if there is a non-intrusive way to do that

tony.kay14:09:51

I really think your best bet is a post-mutation on your last load

tony.kay14:09:22

I don't see a clean way to encompass "queue empty" without significant changes

tony.kay14:09:28

There could be many queues (one for each remote), so it would have to somehow know that all of the queues are empty, but they are async channels with depth, and there is no core async peek. I guess you could do a very short timeout on take, but then you'd end up busy-polling the queues.

tony.kay14:09:52

What's wrong with the post-mutation idea?

claudiu16:09:36

Just triyng to think of ways it can be applied as a "black box". Juat run function x (that may or not have loads) then if no network activity is present do render. The post mutation works but think it can get a bit complicated for stuff like load-actiom, parallel loads, multiple netowrks & loads that also need a post-mutation.

claudiu16:09:09

Noticed that fulcro has two keys in the state for network activity. Trying to see if I can just add-watch on those keys and just flip thr switch when there empty.

claudiu20:09:36

@tony.kay seems to work well with adding a watch on the state and resolving the request when network markers are empty. One catch is that I have to look at two keys (in progress & pending) and also have a case where there emty but my value is nil. For the nil one think its because of the local load , the global marker ui/loading is still true. Any chance fulcro could have a marker like :fulcro/network-activity bool ? (Something like global ui load marker, but applied to all network events and that cannot be turned off)

tony.kay20:09:50

So, the problem with a general network activity marker is parallel loads, I think. If I remember right, the parallel loads don't go through the queue, and Fulcro itself doesn't do any tracking on them (it closes over them with a lambda). It would be possible to add tracking, I guess, but it is a bit tricky. Perhaps I could add some kind of counter for "number of things in flight". It's a reasonable request. In fact, it is kind of a hole that you can't know that network activity (globally) is happening without tracking it yourself. I think the original intention of the global load marker was to be that, but since it doesn't track mutations, it isn't as useful.

pvillegas1220:09:10

@tony.kay have you come across the pattern of loading data for each route (using html5 routing) at the started-callback level but also as you navigate the UI?

pvillegas1220:09:26

(the more I work with fulcro the more I like it :P)

tony.kay20:09:34

I am trying to make sure all features of Fulcro have both a mutation, and a mutation helper. The * suffix on functions generally means they are functions for working on state-map, which can be used inside of mutations. Thus, route-to* is the one you use inside of your own mutations.

pvillegas1221:09:35

When I use nav-to from my components, it triggers that function through the pushy/pushy setup below

tony.kay21:09:52

yeah, that mess of stateful stuff is ugly 😞

pvillegas1221:09:03

but I want the nav-to to do a transact with two different mutations, one for moving the route and another to load data

pvillegas1221:09:41

I get into a circular dependency where I need the routing mechanism and the query from stateful components 🙂

pvillegas1221:09:49

(for the data loads)

tony.kay21:09:03

muations are data...you don't need to require them

tony.kay21:09:30

though if you don't require them, then you have to type out the fully-qualified symbol

pvillegas1221:09:31

In order to load I need a defsc component to construct the query

pvillegas1221:09:53

(that’s what I meant)

tony.kay21:09:58

What I mean is that you are probably requiring the mutations in the UI area so you don't have to qualify the mutation names

tony.kay21:09:14

which creates the cycle

tony.kay21:09:19

but it isn't necessary to require them

pvillegas1221:09:07

ah, got it, I can use the symbol referring to the ns I want

tony.kay21:09:19

Several alternatives: 1. Use the technique described https://github.com/fulcrologic/fulcro/issues/238 2. Put an atom in the mutations ns (e.g. ComponentAtom) and reset! it after your defsc to hold the component (that keeps the requires in one direction, and gets you your aliasing) 3. Do what I said above, and don't require the mutation ns in the UI ns...go in reverse instead.

pvillegas1221:09:37

I’m requiring nav-to in my UI, a fn, not really a mutation per se

tony.kay21:09:08

The technique of splitting your mutations into an "interface" and "implementation" in (3) might work best...it also gets you the advantage of not having to quote your mutation expressions

tony.kay21:09:30

then you can put your mutation implementation anywhere, independent of the declaration of it

tony.kay20:09:05

Thus, you'll typically build a mutation to do your page transitions, which will use route-to* as a building block..then you can combine in db checks and load-actions.

tony.kay20:09:33

It is safe to always add df/remote-load to the remote side of a mutation...if no load-action was submitted in action, it is a no-op

tony.kay20:09:23

I also sometimes use :componentDidMount as a place to put mutations that do things like "link in dropdown options" that are optionally loaded if missing.

tony.kay20:09:49

E.g. I put the dropdown options in some top-level area (e.g. [::dropdown-options :states]) and the link mutation uses the ref of the env in the mutation to link some component prop (via ident) to the dropdown options at root. If the options are missing, then it issues a load with a target.

pvillegas1221:09:54

Would that hook be useful for data loading as well? (assuming you appropriately check for staleness)

tony.kay21:09:02

You just need to understand when it gets triggered...a component can re-mount for various reasons, including a parent key change. So, as long as you're aware of that and cope with it, it's fine

currentoor22:09:09

I have a project based on the shadow-cljs template but I’m having trouble getting the browser cljs tests to work

(ns ^:dev/always ucv.client-test-main
  (:require [fulcro-spec.selectors :as sel]
            [fulcro-spec.suite :as suite]

            ucv.sample-spec))

(suite/def-test-suite client-tests {:ns-regex #"ucv.*-spec"}
  {:default   #{::sel/none :focused}
   :available #{:focused}})

(client-tests)
results in
primitives.cljc:2362 Uncaught Error: Assert failed: (or (component? x) (reconciler? x))
    at Function.fulcro.client.primitives.transact_BANG_.cljs$core$IFn$_invoke$arity$2 (primitives.cljc:2362)
    at fulcro$client$primitives$transact_BANG_ (primitives.cljc:2362)
    at fulcro_spec$runner$novelty_BANG_ (runner.cljc:71)
    at fulcro_spec$runner$render_tests (runner.cljc:76)
    at reporter.cljc:228
    at cljs.core.MultiFn.G__57251__2 (core.cljs:10857)
    at cljs.core.MultiFn.G__57251 [as call] (core.cljs:10843)
    at client_test_main.cljs:7
    at cljs$test$run_block (test.cljs:448)
    at test_BANG___73248__auto___87232 (client_test_main.cljs:7)