Fork me on GitHub
#fulcro
<
2018-03-08
>
tony.kay01:03:41

New 2.3.2-SNAPSHOT on clojars. The new alpha DOM support has been tweaked and tuned. Most combos work properly now. WITH THE EXCEPTION of input, select, option, and textarea…those are still pending.

wilkerlucio02:03:56

@tony.kay nice! just to confirm, the new css syntax does namespace the classes to the current component?

tony.kay02:03:43

no…integration with fulcro-css is something we just discussed…going to use symbols for that

tony.kay02:03:16

so, not working yet, but: (div '.some-class "Hello") will mean “get the css classname from the binding named some-class

tony.kay02:03:28

so, you could defined that in a let or destructure from fulcro-css

tony.kay02:03:46

the :a => {:className "a"}

wilkerlucio02:03:00

humm, is there a way to use multiple namespaced classes with this model?

tony.kay02:03:19

turns out dotted symbols are valid in clj and cljs

tony.kay02:03:30

(div '.some-class.other-class ...) works fine

tony.kay02:03:13

and then we get both global and localized names, with notation that indicates which is which

tony.kay02:03:35

and it isn’t tied to a library…they’re just symbols you have to have defined

wilkerlucio02:03:37

fair enough, looks weird, but I think can get used with time

wilkerlucio02:03:34

I understand this in the point of flexibility, but I was expecting more integration of fulcro-css there, maybe I'm biased because I always use the fulcro css for styling

wilkerlucio02:03:56

but what about using :.class for namespaced css and :$class for unnamespaced (like the fulcro css syntax)?

tony.kay02:03:07

Hm. At the moment fulcro-css is an add-on library

tony.kay02:03:31

tying the internals of the two is questionable in my mind

wilkerlucio02:03:34

the great thing about this would be not having to destruct from the css, that's a bit of pain I think

tony.kay02:03:48

I agree it reduces boilerplate

tony.kay02:03:05

but it also makes me want to pull fulcro-css into fulcro proper and not have a separate lib

wilkerlucio02:03:28

my first impression is that could be a good thing

tony.kay02:03:30

@currentoor what are your thoughts?

tony.kay02:03:51

I don’t really want to combine them. Pulls garden into everyone’s server deps

tony.kay02:03:16

The advantage of the symbol is you can compute classes in a let as well

tony.kay02:03:23

which is a common thing to do

tony.kay02:03:46

the :.a is recognized by a lot of ppl fro mSablano and hiccup

wilkerlucio02:03:49

yeah, in terms of flexibility the current idea seems to win

tony.kay02:03:12

AH, I’ve got it: fulcro-css could have it’s own dom ns

wilkerlucio02:03:13

good thing we can keep that on alpha for a while and experiment around it

wilkerlucio02:03:23

humm, interesting

tony.kay02:03:33

OR, we could make the css kw converting pluggable somehow

tony.kay02:03:12

not sure how the pluggable works without being a pain, though (or hurting RT performance)…a lot of this is being done in macros AND at runtime, depending on the combo

tony.kay02:03:54

so plugging would have to happen before the macro eval, and that is ugly

tony.kay02:03:14

so, a dom lib in fulcro-css is kind of appealing to me.

tony.kay02:03:52

for that matter, THIS dom namespace in fulcro-css perhaps causes your argument to win (though support for syms would still be useful)

tony.kay02:03:29

that way the old DOM just stays where it is, and if you want the new cooler syntax you use fulcro-css, which is a super-thin lib that you should really be using anyway 🙂

tony.kay02:03:10

then maybe fulcro-css becomes fulcro-dom, which was another request we had…export the DOM stuff for react as an add-on lib.

wilkerlucio02:03:42

cool, I'm hosting some guests now, have to leave the computer, let's talk more later

tony.kay02:03:27

@currentoor I’m porting a larger app, and there are definitely some problems still with alpha dom. Using fn macro isn’t happy, for example, for callbacks.

tony.kay02:03:31

basically using any macro within the props map isn’t ok

currentoor03:03:42

i prefer fulcro-css be part of fulcro proper, i think the value it provides is worth the added complexity, is there any way we could add it by default and opt out if needed? i think we should be doing more to encourage fulcro-css

tony.kay03:03:35

hm. that really wasn’t one of the options I mentioned…but I see your viewpoint

tony.kay03:03:48

what does garden pull in?

currentoor03:03:00

com.yahoo.platform.yui/yuicompressor

currentoor03:03:08

i already checked 😅

tony.kay03:03:58

not much, it would seem

currentoor03:03:56

pluggable seems nightmare-ish unless we do it all at runtime

tony.kay03:03:04

I agree pluggable is a no go

currentoor03:03:53

if we agree that fulcro-css is a good thing to use in general, perhaps we should embrace that?

tony.kay03:03:12

what do you think of :$a for global classes?

currentoor03:03:39

only if we bring fulcro-css in, otherwise if we decide to keep things separate then this goes against keeping things separate

tony.kay03:03:19

so, if the plan were to bring it in, what about the hiccup/sablano users?

currentoor03:03:03

how are they affected?

tony.kay03:03:47

just sayin that there are a lot of ppl in the react community that will see the difference as an annoyance if looking into Fulcro

currentoor03:03:36

oh as in they’d rather use sablano with defsc?

tony.kay03:03:00

no, I’m saying they’re used to seeing :div.a not :div$a

tony.kay03:03:42

so it would be initially annoying to them (if they have external CSS, like they might) to have to use $ instead of dot

tony.kay03:03:59

it’s a minor concern, but ppl get touchy over syntax and notation

currentoor03:03:18

seems like a valid concern now that you mention it, what if we reversed the notation? :.a is not namespaced but :$a is namespaced?

currentoor03:03:36

or some other character?

tony.kay03:03:38

no, garden supports both

tony.kay03:03:46

$ actually means global in garden

tony.kay03:03:56

or rather fulcro-css

currentoor03:03:29

which would be a breaking change we don’t want?

tony.kay03:03:51

so, you say

(defsc Comp [this props]
  {:css [[:.a ...]
            [:$a ...]]}
  (div :$a (p :.a "Hello")))

tony.kay03:03:10

if you just defined it, it would be nice to then just use it without destructuring

currentoor03:03:33

yes, exactly

currentoor03:03:50

i believe that was @wilkerlucio’s point too

tony.kay03:03:06

more boilerplate gone, which I like

tony.kay03:03:55

and if you’re using fulcro-css, you get to use the dots all over the place 😜

tony.kay03:03:11

Fixed the inclusion of code bug in the new dom

tony.kay04:03:50

So, the problem with kws that use fulcro-css conventions is that the containing class is not known when the elements are being evaluated…it turns it into runtime overhead, and that runtime overhead also involves using a dynamic var….don’t like either of those

tony.kay04:03:06

right now the kw eval can mostly happen at compile time

tony.kay04:03:36

So, I’m back to: Fulcro-css could have it’s own dom functions, or the symbol eval

tony.kay04:03:14

the symbols are fully general, work with let expressions and fulcro-css, and don’t incur weird overhead unless you use them…even then you can still do partial evals at compile time

currentoor04:03:45

i wonder if fulcro CSS could be modified to better serve this usecase?

currentoor04:03:05

like why can’t it expose it’s classes at compile time?

tony.kay04:03:26

the problem is evaluation order

currentoor04:03:00

what do you mean?

tony.kay04:03:19

all the mess of “might be done in the macro, might be done at runtime”

tony.kay04:03:35

nested macro calls

tony.kay04:03:03

it sounds like quite a tangle to get the symbol from an outer macro down into the inner macro, transparently

tony.kay04:03:41

it’d almost have to be a pre-transform in defsc of the body instead

tony.kay04:03:34

that’s an interesting idea

tony.kay04:03:44

what if that was just an option to defsc?

tony.kay04:03:16

where it would scan the body of the render at compile time and transform the keywords if you set something like :use-css-keywords true in the options map

tony.kay04:03:30

or perhaps if you use :css at all

tony.kay04:03:09

we know all of the tag names

currentoor04:03:31

so that could turn all the keywords into :$name$name2 something like that?

tony.kay04:03:10

you’d type the $ ones

tony.kay04:03:25

but if you used a . one, it would get the class localized onto it

currentoor04:03:54

oh it would do .items-wrapper to .fulcro-css_cards-ui_ListComponent__items-wrapper depending on context?

tony.kay04:03:22

if second arg of a known tag call

tony.kay04:03:33

(ignoring ns of sym, and requiring pattern match on kw)

tony.kay04:03:09

that’s a lot better

currentoor04:03:26

does the outer macro get expanded first?

currentoor04:03:34

opposite of functions right?

tony.kay04:03:48

oh, good question…don’t remember 😜

currentoor04:03:51

i was going to suggest defsc puts the fulcro-css_cards-ui_ListComponen in a dynamic var that child macros have access to

currentoor04:03:17

in a map called *context* for other things like this

currentoor04:03:15

and the child dom macros do their own re-writing (kw literals only allowed)

tony.kay04:03:22

that is already the case (literals only)

tony.kay04:03:51

It seems macros go outside in: the body is unevaluated, then the output is re-evaluated

tony.kay04:03:08

right, because macros could output things that are other macros

tony.kay04:03:11

so, it has to be that way

currentoor04:03:41

(defsc ListComponent [this {:keys [id items]} computed {:keys [items-wrapper]}]
  {:css         [[:.items-wrapper {:background-color "blue"}]]
   :css-include [ListItem]}
  (dom/div :.items-wrapper
    (dom/h2 (str "List " id))
    (dom/ul (map ui-list-item items))))

currentoor04:03:45

that’s what i was thinking

tony.kay04:03:57

composition is not good, though, for this solution. If you define some function or macro that contains other code, it won’t be in context for translation

tony.kay04:03:57

the symbols are just better. They’re a little more boilerplate for destructuring on the first line, but they completely compose…you can pass them along to other functions, etc.

tony.kay04:03:45

BTW, I punted on inputs, alpha DOM now has them, but they are a non-wrapped variety. Use fulcro.dom form elements (without the sugar) if you need wrapped for now. I’ll integrate the wrapped into the new syntax in the coming days.

tony.kay04:03:24

So, @currentoor what do you think? Move forward with symbol support instead of all of this other mess?

currentoor04:03:46

(defsc ListComponent [this {:keys [id items]} computed {:keys [items-wrapper]}]
  {:css         [[:.items-wrapper {:background-color "blue"}]]
   :css-include [ListItem]}
  (dom/div '.items-wrapper
    (dom/h2 (str "List " id))
    (dom/ul (map ui-list-item items))))

currentoor04:03:54

that still looks pretty good IMO

tony.kay04:03:50

I think so, too. It isn’t quite as “special”, but the problems with the localized css seem pretty ugly

currentoor04:03:58

i’m with you on moving forward with the symbol stuff, but i’ll have to work on it tomorrow

currentoor04:03:21

maybe @wilkerlucio can weigh in by then too

tony.kay04:03:47

Yeah, I really don’t see how to make the keywords work reliably, given all of the execution contexts and composition possibilities. Bugs would be a pain to figure out, and would be mysterious to users.

tony.kay04:03:18

makes my head hurt…the symbols are a little work to code, but they “make sense”

levitanong10:03:52

in the new networking system, when using custom remotes to legacy APIs, is it preferable to make a new record that implements FulcroRemoteI, or use the existing fulcro-http-remote, and pass in custom middleware?

wilkerlucio13:03:25

@levitanong depends on how much customization you need, if fulcro-http-remote can handle your needs, go for it

levitanong13:03:13

@wilkerlucio AFAIK it’s not meant for use with REST APIs. I’m currently trying to go with the method wherein i just make a record which implements FulcroRemoteI, but i’m kind of hitting a brick wall with ok-callback. is there anything else besides {:transaction ... :body ...} that I have to know about regarding ok-callback?

wilkerlucio13:03:56

@levitanong I think you can use for REST api's as well, if I don't remember wrong @tony.kay was using it like that for some contract project. about the custom impl, I think :transaction and :body are all to know, I had issues when I tried that first because I missed those. What's happening on your case, the callback is not been triggered?

levitanong13:03:38

@wilkerlucio the data doesn’t seem to be merged in. When I checked the transaction log, the merge is showing that the :data-tree has :not-found as a value in its keys.

wilkerlucio13:03:54

merging problems usually happen when there is mismatch of query/data, did you confirmed the data is in the right shape?

levitanong13:03:30

as far as i can tell, yes. Especially since i was previously using FulcroNetwork, and it was working

levitanong13:03:32

if I remove :transaction, should it still merge into state, just skipping the normalization step?

levitanong13:03:19

also, perhaps this will be relevant: I’m using df/load

wilkerlucio13:03:41

I don't know that much about the new internals, what I can tell you is that the old one is not likely to go away, so you can still use that

wilkerlucio13:03:10

I can't debug with you now, I have to leave, but we can talk more later, or Tony can probably have a better idea on what might be going on, sorry can't help you more now

levitanong13:03:18

thanks for your time, @wilkerlucio. It does seem the old system will disappear though, as it’s been labelled as deprecated.

levitanong13:03:28

have a great day! 🙂

wilkerlucio13:03:20

thanks! same to you 🙂

wilkerlucio13:03:49

it just means new stuff should try to use the new one, but we try to follow the "don't break things" rule as much as possible 🙂

levitanong13:03:06

good to know! thanks again.

tony.kay15:03:00

@levitanong read the source of the implementation if you're going to implement your own. There are two models I'd recommend for REST: if you only ever need one network request per query, then middleware. If multiple, then wrap the new http implementation, don't go all the way to low level. The implementation doesn't care what is in the request. No reason at all to implement xhrio behavior at all

levitanong15:03:51

@tony.kay what do you mean by wrapping the new http implementation?

tony.kay15:03:00

Make a new RemoteI that uses the FulcroHTTPRemote to do the networking.

tony.kay15:03:48

It's fully general for doing single low level requests of any kind

tony.kay15:03:33

As in it calls ok or error exactly once

tony.kay15:03:37

Be careful that you understand the current middleware. The response middleware in particular for your case

tony.kay15:03:07

And that no middleware goes in by default

tony.kay15:03:44

Well, depends on how you create it :)

levitanong15:03:27

oh interesting

levitanong15:03:02

you mean to say i instantiate a FulcroHTTPRemote, and call those methods from within some outer record that implements FulcroRemoteI?

levitanong15:03:06

I was actually considering to also make a request middleware to change the url/query-params, etc…

levitanong15:03:29

relevant to the query

tony.kay15:03:07

right. So, the normal response middleware just rewrites the (plain text) body from transit:

tony.kay15:03:56

so, for FulcroRemoteI, you have to return a map with a body and transaction

levitanong15:03:18

Yeah, I’ve tried this, but somehow things aren’t working. 😅

levitanong15:03:49

do you know if there are any gotchas when using df/load?

tony.kay15:03:14

so, loads get queued individually, but combined into a single query where possible

tony.kay15:03:23

so, you may see multiple loads in a single network request

levitanong15:03:01

i’ve commented all but one to isolate that possibility

levitanong15:03:20

i’ve also made the class argument of df/load nil to avoid normalization

levitanong15:03:29

(in which case I’d assume the transaction key would not be necessary

tony.kay15:03:42

the transaction key is always necessarey

tony.kay15:03:51

a query is always sent, and must match the response

tony.kay15:03:03

you just made the transaction a keyword, instead of a join

tony.kay15:03:21

t: [:k] means b: {:k value}

levitanong15:03:29

yes, i’ve seen this as well

levitanong15:03:53

I’ll make a minimal case and see what happens 😄

tony.kay15:03:38

for a load, you have the burden of making it match, actually….let me think about that

tony.kay15:03:52

as in, I’m not sure rewriting the transaction will work

levitanong15:03:09

some lost metadata?

tony.kay15:03:24

lost metadata would kill your normalization for sure

levitanong15:03:38

but if i’m not using normalization, the metadata wouldn’t matter though, right?

tony.kay15:03:04

so, loads are special. The transaction morphing works fine for mutations

tony.kay15:03:20

but loads go through a much more detailed process.

tony.kay15:03:40

just a min…let me refresh my memory

levitanong15:03:28

take your time 🙂

tony.kay16:03:05

So, for any given sequence where you’ve queued loads (you held the thread, issues more than one load):

tony.kay16:03:01

1. Those loads are combined into a single query 2. The individual loads are remembered, and the data fetch “loaded-callback” is called with the load items, because each could have fallbacks, post mutations, targeting, etc. 3. So, the transaction for loads is ignored

tony.kay16:03:16

and the body must match the incoming query

tony.kay16:03:54

I’m guessing the documentation isn’t quite right for this part…

tony.kay16:03:29

So, processing (load this :x nil) should call the ok with {:x value}. Period.

tony.kay16:03:19

and the remote code must examine the transaction to see what all is combined. You’ll end up writing a parser at the network layer, typically, to process the query and figure out what all you need.

tony.kay16:03:31

At the networking layer you could leverage core.async and such for coordination among the different REST calls you might make…and yes, middleware on the lower level remote would let you easily set things like headers and method.

levitanong16:03:50

hang on. you mean to say that for loads, i should pass the novelty naked instead of wrapped with {:transaction ... :body novelty} to the ok-handler?

tony.kay16:03:17

no, you must use the :body yes

tony.kay16:03:29

:transaction is technically pulled, but not used (for loads).

levitanong16:03:11

it’ll take some time for me to digest this i think

tony.kay16:03:30

The ok is on-load here

tony.kay16:03:52

you can see that the load items are the thing of interest, so it closes over them, and only uses the first arg. The first arg at this layer is the body

levitanong16:03:15

re: core.async, you mean i should use go to wait for both network requests to complete before passing them on to ok?

levitanong16:03:29

i remember running into this before, and worked around it by setting :parallel to true 😛

tony.kay16:03:03

For a given query, you must call ok once and only once.

levitanong16:03:32

yeah, so if i use parallel, the multiple calls to df/load end up as single individual queries

tony.kay16:03:45

that is what releases the load queue. If you use parallel, Fulcro doesn’t use a queue and doesn’t care.

tony.kay16:03:00

but then your end users could suffer by calling it wrong and hanging the whole mess

tony.kay16:03:16

you should write the internals to be robust instead

tony.kay16:03:26

it’s ok for you to issue internal parallel requests

tony.kay16:03:53

but yes, you have to manage that at the networking level. The model doesn’t get rid of the fact that js is async…just isolates it to the lowest layer as much as possible

tony.kay16:03:06

and that’s where you’re coding 🙂

tony.kay16:03:28

So, perhaps it would help to trace through a load for you: 1. You issue one or more loads (they go into a storage queue, not an async one) 2. The remoting layer is triggered, and pulls as many load items as it can from the storage queue 3. As many of those that are compatible (don’t share the same dispatch key) are turned into a single query 4. A callback handler is generated to handle the result. That callback handler is given the list of load items that must be processed. 5. The application layer creates ANOTHER callback that can call (4) with the result (body), but only the result. 6. The resulting callback and combined query is placed onto an async queue for the remote in question 7. An infinite go loop pulls things from the async queue. It wraps OK and ERROR with code that will put something into a core.async response queue, and calls that remote with it, then waits by doing a take on the response queue 8. The callback in (7) is what you see at the network layer. When you call it, it releases the go loop, and passes the data through the chain…like a middleware chain

levitanong16:03:32

ok, so i understand

levitanong16:03:14

but as I understand it, there shouldn’t be much of a problem if i only issue one unnormalized load for a remote (say at startup)

levitanong16:03:11

and calling (ok-handler {:transact [:foo] :body {:foo :bar}})

tony.kay16:03:32

that should be correct

tony.kay16:03:04

transmit gets a map with namespaced kws

tony.kay16:03:27

you’re pulling ok-handler from that

levitanong16:03:43

yeah, that’s definitely above board.

levitanong16:03:19

the odd thing is i’m getting a {:foo :fulcro.something.something/not-found} in my state.

levitanong16:03:55

ok so now i know what the expected behavior is, I can work towards building a minimal case to hopefully either find a bug, or find a problem with what i’m doing. 😛

levitanong16:03:06

i’ll get back to you soon! thanks for your time, @tony.kay!

tony.kay16:03:19

trying to think how you could be getting not found

levitanong16:03:38

wilker mentioned that one usually gets that through faulty normalization

tony.kay16:03:48

mismatch of the query (incoming EDN in the case of a load) and the response you give

tony.kay16:03:36

The whole power of the entire Fulcro story for this is that you send a graph query, and get a normalized result in your database. That is done by tree->db, which uses the query and tree of data

tony.kay16:03:38

nothing new

tony.kay16:03:54

your response is merged via that function and the original query

tony.kay16:03:10

if they don’t match, then the query is asking for something that isn’t found in the response

tony.kay16:03:31

The normalization step will only convert the stuff that is in the query

tony.kay16:03:04

If I tell it “OK” with EDN of [:x] and give it {:x 1 :y 2} the :y stuff is thrown away

tony.kay16:03:28

as far as Fulcro is concerned, the network layer gave it stuff no one asked for…i.e. the low layer did a poor job and over-queried.

tony.kay16:03:44

If there is no query for a bit of data, there can be no conversion of that data into the database. It is “unsafe”…the user didn’t ask for y and would be surprised if it did something like overwrote an important value they cared about. It would be mysterious

tony.kay16:03:18

So, the low layers of load are not allowed to “override” what the user expects from an explicit load query

tony.kay16:03:25

You have to be in the “lower abstraction layer” mindset when working at the network layer here. The higher level abstraction is “the user asked for :x“.

tony.kay16:03:15

Of course, from that argument, one could say that allowing the middleware access to the tx for mutations breaks that abstraction a bit, which is true. But with a mutation, though, there can be the idea that some result from the server should cause some arbitrary change to your database.

tony.kay16:03:50

So I think it a reasonable relaxation of the constraint.

myguidingstar16:03:26

@wilkerlucio in case you haven't seen it, I made a PR to pathom

myguidingstar16:03:14

btw, walkable should work well with placeholders now

wilkerlucio17:03:20

@myguidingstar nice, glad to hear, I got the notification, just didn't had the time to stop and do a proper code review, I expect to check on it before next week 😉

wilkerlucio17:03:59

@tony.kay @currentoor just read the discussion from yesterday, seems like you guys went though a mess of macros 😛, seems like the full integration is a pain, the symbol solution sounds like something nice, but having to destructure feels like more work than the current impl, right now what I do is something like this:

(defsc SomeClass [this props _ css]
  {:css [[:some-class {:color "#000"}]]}
  (dom/div #js {:className (:some-class css)}
    "bla"))

wilkerlucio17:03:55

I just had a though, what if we use some custom reader with a custom attribute, let me write an example of what I'm thinking

tony.kay17:03:10

vs.

(defsc SomeClass [this props _ {:keys [some-class]}]
  {:css [[:some-class {:color "#000"}]]}
  (dom/div '.some-class "bla"))

wilkerlucio17:03:34

what I don't like about that is the repetition, I have to write same class name at least twice for every usage

tony.kay17:03:06

yeah, but you’re not saying :className over and over. And it isn’t repitition in the non-DRY sense…it’s just a compact definition, lookup, and use.

wilkerlucio17:03:31

on the format I wrote I can have snippets that write the boilerplate for me, but I can't have a snippet that knows about how to add destructuing on defsc

wilkerlucio17:03:10

(defsc SomeClass [this props _ css]
  {:css [[:some-class {:color "#000"}]]}
  (dom/div {::fp/class :some-class} "bla"))

(defsc SomeClass [this props _ css]
  {:css [[:some-class {:color "#000"}]
         [:other-class {:background "#fff"}]]}
  (dom/div {::fp/class [:some-class :other-class]} "bla"))

wilkerlucio17:03:53

(maybe use ::css/class instead, thinking now this keyword makes more sense on css namespace)

tony.kay17:03:55

still have the context and omposition problem

wilkerlucio17:03:10

I was thinking convert at macro read time

tony.kay17:03:15

that’s worse

wilkerlucio17:03:33

is it? by using a fully qualified namespace it can be easy to walk and replace the values

currentoor17:03:56

i’d rather have less boilerplate, ^ solution seems worse IMO

tony.kay17:03:06

(defmacro X [stuff]
   (div ... use your stuff))

(defmacro div ...)

(defsc (which is a macro) (X ...))

tony.kay17:03:30

it’s the same composition problem: I can’t figure out what component I’m nested in reliably

tony.kay17:03:00

in this case they’re all macros, but combine in some symbols that have to be evaluated at runtime and you lose all composition

wilkerlucio17:03:40

what I was thinking is: the defsc always know the full symbol, and it runs before the div macro, in this case I'm cutting out the possibility for symbols here, you should only use the keywords so it gets easy to translate into the full class names

wilkerlucio17:03:08

if you need to use symbols for dynamic class, fallback to other solutions

donmullen21:03:37

@tony.kay In development - I am seeing [fulcro.client.primitives] component nycdvp.ui.property/PropertyDetail's ident ([:property/by-bbl nil]) has a nil second element. This warning can be safely ignored if that is intended. after I click on a row that triggers a server load. The property detail page then updates once the data is in. On production server (with ‘release’ build), however, clicking on a property results in the whole screen going blank - and an Uncaught TypeError: Cannot read property 'log' of null which I haven’t investigated yet. Is there something I need to do to prevent the nil second element during a load - is it an issue? Heading to fulcro.book now to research.

donmullen21:03:58

I believe post-mutation is what I need - I was running mutation after load call.

tony.kay21:03:54

@donmullen are you using React 16?

tony.kay21:03:45

uncaught exceptions do that in React 16...you have to define more code to isolate them. That warning, as you found, typically means there is some kind of data disconnect

tony.kay21:03:26

there could be a bug in logging as well, that is giving you the exception you report. That sounds like logging was attempted, and the logger, perhaps, was nil?

donmullen21:03:28

@tony.kay - Yes 16.2.0. Removing the prim/transact! to a post-mutation on the load resolved the issue. It does seem like in production logger was nil, yes. Would that be the fulcro logger?