Fork me on GitHub
AJ Snow00:09:51

I'm getting the sense that fulcro is better approached from a bottom up perspective if I want to modularize stuff.

AJ Snow00:09:10

ok I made an example that sort of captures how I've been thinking about this.

AJ Snow01:09:36

(defsc ImageContainer [this {:image-container/keys [id src alt] :as props}]
  {:query [:image-container/id :image-container/src :imag-container/alt]
   :ident :image-container/id
   :initial-state (fn [{:keys [id src alt] :as params}]
                    {:image-container/id id
                     :image-container/src src
                     :image-container/alt alt})}
  ;css/context + add id attr + maybe surround with dom/div or more
  (dom/img {:src src :alt alt}

AJ Snow01:09:42

I decided to commit to the image example since I'll have to deal with it eventually. Is this the right sort of approach to building components? If I want to build a container so that all the images have the same shape then this would make sense I think. I could use this in a parent's initial state and pass it the context the parent knows to build the component. The problem though would be the parent's design constraints. I can't make an arbitrary number of image containers and making a large number of them in the parent would get excessive, especially in the initial-state and the parameter list. For example, if the parent is a component that uses, say, four image containers then that's four parameters to add to the header. I need to read up on the data flow after the initial state. Once the initial state is created, what do the parameters and query do for me?

AJ Snow01:09:19

yeah the more I think about this the weirder it gets. I have to be thinking about this wrong. So If I define a component that uses a bunch of sub components then that just explodes the size of the initial state since I have to define both what the subcomponent gets and all the components of that sub component and all they get

AJ Snow01:09:30

hmm, if I want to deal with that then I could maybe define an instance of a component if I know the data will be mostly or completely static. Very few things on the page actually communicate data so defining instances of compositions of components makes sense.

Jakub Holý (HolyJak)08:09:55

Wouldn't the parent component simply get a list of images and map Image Container over it? Normally you would get data from Pathom instead of hardcoding them in initial state. Not sure where you want the images data to be defined, in the parent component?

Jakub Holý (HolyJak)08:09:12

Look into the book at the person list example. Isn't it the some, only you query for types of images (ie "dog list" instead of "friends list") and display each via Image Container instead of Person?

AJ Snow22:09:16

I figured the parent component would define the source (or get it from its parent) but I think your right. I was looking at the person example last night and I'm pretty sure I'm just thinking about the design wrong. I'll see if I can't get something that resembles the person example


I’m happy to announce the release of Fulcro 3.2.16. This version adds a new plugin to support completely synchronous operation (sans remotes) which can be used to improve regular application performance, but can also be used to enable trivial full-app testing that has no asynchrony even in js. It also removes some internal debugging logic that was unnecessary and affected dev-time performance. See the new chapter in the book at:


Thanks to the Folks at Dataico for funding this cool addition: @pvillegas12 @dansudol

🔥 24

Be sure and check out the cool new testing abilities this adds:


BTW, that testing works in CLJC…I’ve gotten in the habit of writing all of my Fulcro code in CLJC (which is only slightly painful in UI…just stub all the low-level js stuff out with #?(:cljs …) ). This lets me run all of my tests in a normal Clojure REPL with a simple kb shortcut, which is very nice since the CLJ runners are much more full-featured.

eccentric J04:09:42

Just cloned the fulcro-rad datomic-cloud branch from the repo and ran the recommended commands. I’m visiting the http server at 8081 but I’m only seeing a blank, brown page. Is that expected?

Tyler Nisonoff04:09:43

It should be port 3000 8081 is the shadow http server but it’s not used in the demo repo

eccentric J04:09:59

Isn’t that 9630?

eccentric J04:09:26

I was wrong, you are right

Tyler Nisonoff04:09:44

There’s the server and the http dev server

Tyler Nisonoff04:09:52

But the Fulcro backend is on 3000

👍 3
eccentric J04:09:58

[:main] Compiling ...
------ WARNING #1 -  -----------------------------------------------------------
 Resource: node_modules/semantic-ui-react/dist/commonjs/lib/AutoControlledComponent.js:219:2
 JSDoc annotations are not supported on return.

Adrian Smith08:09:21

Sounds like an issue in semantic ui itself which is a javascript ui library, should be safe to ignore but if not maybe try bumping the version on it?


So I just did some performance/behavioral analysis on the differences between the standard tx processing and the new pluggable synchronous version. Of course they both do roughly equivalent work, so the overall CPU usage is roughly equivalent, but here is an example of where your end users would experience differences. The scenario is the full-stack TodoMVC app, where an item is being added to the list. This involves: • An optimistic update to add the item to the list • A network request to add it on the server • A server response (which could result in data changes..tempid remapping, etc.) • A secondary render to update the view based on the server result The old tx processing does everything asynchronously, and schedules animations using requestAnimationFrame. The result looks like this in a flame chart:


Notice the network request at the top. The overall time from where the user presses “Add” to the final network result refresh is about 81ms.


The new synchronous tx processing on the same interaction looks like this:


Notice the network request starts while the initial tx processing is still running, and actually completes before the final DOM refresh of the keypress (7ms), triggering the UI update for the network result. Total time from keypress to completion of final render after network interaction: 15ms. Again, no CPU overhead difference…they both consume the same processing time; however, the new one feels like 60fps with full stack, whereas the old one feels more like 10fps.


So, not only does the new tx processing make for interesting sync testing possibilities, it leads to dramatically improved user perception of “snappiness” in full-stack scenarios.

👍 18
❤️ 6
🚀 9

f-in-a .. its so good .. wow