Fork me on GitHub
#fulcro
<
2018-01-24
>
currentoor00:01:55

@cjmurphy not sure how to do that, cuz that would put a collection of them in the normalized portion of app state for that component, where i wan these at the root table

cjmurphy00:01:51

So you are loading links.

cjmurphy00:01:05

@currentoor What about just loading at :started-callback?

cjmurphy00:01:21

And I wonder if the root component's initial-app-state will put links in.

currentoor00:01:52

:started-callback is similar to post-initial-load mutation but it might trigger an extra render

currentoor00:01:06

root component seems like a promising idea, didn’t think of that

currentoor00:01:11

i’ll try that

currentoor00:01:21

oh yeah that worked! thanks @cjmurphy!

tony.kay01:01:50

@currentoor I have used the Root as an option, though then you have something permanently in your root query that you don’t need. The merge-component! is good for this in started-callback. It includes named parameters for plugging idents in. I’ve also used initial state. Those are the top 3 options.

tony.kay01:01:27

@macrobartfast There’s an old Untanged video where I try to show the devcards approach. I like that approach a lot.

tony.kay01:01:11

It refers to all of the old names, but the technique is the same

tony.kay01:01:16

I need to make a new video that does a bigger better job of that. Perhaps I’ll do that soon.

tony.kay01:01:20

@macrobartfast actually, re-watching that video it doesn’t cover what you want…I never did make a video for it, but thought I did…I think it was meant to be the sequel of that one 😕

tony.kay01:01:17

@currentoor Oh, um..yeah, you can technically do that. I was more thinking of doing a tree and adding a query to normalize it into the table.

tony.kay01:01:13

(defsc Root [this props]
  {:initial-state {:things [... list of things ...]}
   :query [{:things (prim/get-query Thing)}]}
...)

currentoor01:01:17

oh i see, yeah i already have it normalized (it’s not very nested to begin with since widgets don’t have any sub entities with idents)

tony.kay01:01:47

right. if you do it the way I wrote it, you get full normalization, but the root query has this extra “thing” in it

tony.kay01:01:03

merge-component! is really meant for handling this case in general (from startup or anytime later)

tony.kay01:01:49

and since it allows you to also integrate the generated ident(s) into many places, it is more succinct for that as well

currentoor01:01:51

has anyone seen this error?

Exception thrown by hook while handling onSetChildren: 
Invariant Violation: Item must have been set

currentoor01:01:24

been seeing it a lot more since i upgraded to the fulcro 2.1.2

tony.kay01:01:54

rings no bells for me

currentoor01:01:06

hmm, must be something on my end then

currentoor01:01:40

we used a number of JS libs for react components, upgrading those is going to be a pain

currentoor01:01:44

seemingly simple things can take so long to implement, like an async auto complete multi select component

tony.kay01:01:28

js libraries are currently easier to work with from shadow-cljs

currentoor01:01:41

has anyone tried integrating some of the google closure ui components into an untangled app?

currentoor01:01:59

i wonder if it’ll be as hard as something like D3

tony.kay01:01:14

I’ve not, but I have ported some of the bootstrap ones, and that was straightforward (if you wanted cljs versions for easier SSR), and I’ve used semantic UI React components. So far, I’m leaning towards “it’s easier to grab the CSS and write your own” for most things…because they have very little js…they’re mostly CSS. There are a few cases where the amount of js is large, and it makes total sense.

tony.kay01:01:47

The only thing I try to avoid (if possible) are components that leverage a lot of local state (cannot be controlled by app state), since that makes the play less nicely with our extended story

tony.kay01:01:13

(Fulcro Inspect, support viewer, history navigation, error recovery models that rely on history nav, etc.)

currentoor01:01:18

yeah that’s a good point

tony.kay01:01:30

D3 is a special case, in that it totally wants control of the DOM it manipulates. It is nice in that it is data-driven, so I don’t find it that hard…it just needs that isolation layer between React and D3 (shouldComponentUpdate -> false)

tony.kay01:01:43

Semantic UI React seems nice because everything seems to have a controlled version. That’s usually what I look for. The downside of using pure js components is that SSR gets harder (you have to use Nashorn with some polyfills)

tony.kay01:01:20

but there again, you can write a CLJC wrapper of a component that outputs something with the correct DOM/CSS for SSR (Clojure), and avoid Nashorn that way

currentoor01:01:30

how’s the performance of using Nashorn?

currentoor01:01:53

can you actually beat time to render by using a JS engine inside the JVM?

tony.kay01:01:55

It’s ok, but it adds in this large lump of complexity

currentoor01:01:08

vs just rendering in the browser

tony.kay01:01:25

so, what you’re looking for in SSR is two-fold IMO: Low-bandwidth response time and SEO

tony.kay01:01:29

SEO isn’t time-sensitive

tony.kay01:01:49

and low-bw response is about amount of data. Sending the initial DOM is likely much smaller that the js

tony.kay01:01:05

so on slow networks, the pre-rendered DOM is usually a win

tony.kay01:01:37

I was getting (warmed up) render times on the server under 100ms…I seem to remember even as good as sub 10-ms

currentoor01:01:10

using Nashorn or just clj?

tony.kay01:01:19

clj is hyper fast

tony.kay01:01:28

like microsecond generation times

tony.kay01:01:41

well, 100's of micrseconds…sub 1-ms

currentoor01:01:47

lol too bad java applets never took off

tony.kay01:01:54

then there’s that 🙂

tony.kay01:01:17

So, the struggle was that Nashorn was a PITA at times

tony.kay01:01:39

hard to figure out the errors, very slow startup-times…it just added a ton of drag to development.

currentoor01:01:50

yeah i can imagine

tony.kay01:01:04

so, if you use it, I’d highly recommend SSR be a separate path you don’t turn on during primary development.

tony.kay01:01:22

and that you only ever SSR the (hopefully few) public pages

tony.kay01:01:47

then it is less important that many of your js components work with SSR. Their cljc wrapper can just return nothing on the clj side (because they don’t appear on those pages)

currentoor01:01:09

maybe SSR would be easier if you’re using node.js on the backend

tony.kay01:01:40

same browser env problems, and then your’e dealing with node for your back-end 😜

currentoor01:01:41

though i’m not familiar with the dev workflow there

tony.kay01:01:34

The idea of talking to databases with libraries that have to deal with the node limitations and IO interfacing was not fun when I tried it, but it’s been a while.

tony.kay01:01:20

Anyway: If what you have for your SSR pages is content that can easily be written in cljc, that is by far the superior option. It works really well

tony.kay01:01:29

much better than any js engine

tony.kay01:01:27

If you have to use complex js components on those pages, you can possibly still capture the output from a browser and make that the “clj” side of the cljc wrapper….many components have the same initial “look” every time

tony.kay01:01:33

(defn ui-async-dropdown-autocomplete-thingy [props]
   #?(:clj (dom/div ... what it looked like initially in the browser)
        :cljs (js/call-the-js-thing)))

tony.kay01:01:31

If I can get away with it, then this is by far my preferred approach. The overhead in this wrapper is very small (load the page in a browser and copy/paste through my HTML->CLJ converter…http://book.fulcrologic.com/#_converting_html_to_fulcro). It works, SSR is now pure JVM code (fast and trouble-free). Contrast that to “it renders correctly through Nashorn” where the problems are very hard to diagnose, and you might waste 2-3 days making it work well….and it’s fragile and breaks in ways that require 2-3 more days at some later time(s).

currentoor01:01:42

by capture the output from a browser do you mean the raw HTML? or try to reconstruct it by hand?

tony.kay01:01:18

yeah, raw HTML, run through that utility….bingo, “static DOM generator” for clj

tony.kay01:01:04

even if your “static render” is a little off (maybe the label of the dropdown is blank instead of based on the props) it is still “close enough” for a static page that you cannot yet interact with anyway.

currentoor01:01:08

that’s nifty

tony.kay01:01:24

thanks…I’m big into “good enough but efficient”

tony.kay01:01:51

Nothing worse than spinning your wheels on perfection that doesn’t really get you much

tony.kay06:01:19

@macrobartfast I made a part one workflow video. I’m uploading it to YouTube. It’s a little long (almost an hour), which is longer than I like to go, but I’d appreciate feedback to know if it helps move things along for you. I plan to make a second part soon that steps through some server-side development steps in the same kind of style (Here’s my goal, and here’s how to approach it with minimal overhead/confusion) if it seems useful.

mitchelkuijpers15:01:22

If there are any dutch fulcro users here or you are in the neighbourhood we are organizing a fulcro meetup in our new office: https://www.meetup.com/Avisi-Techdays-TostiTalks-Arnhem/events/246928860/

grzm23:01:25

Is there a pattern for calling a mutation from within another mutation?