Fork me on GitHub
#fulcro
<
2018-10-25
>
currentoor00:10:51

@hmaurer for the first question you can do this

(ns app.intro
  (:require [fulcro.client.cards :refer [defcard-fulcro]]
            [app.ui.root :as root]))

(defcard-fulcro sample-app
  root/Root
  {}
  {:inspect-data true})

currentoor00:10:12

for mutation logging i believe fulcro inspect is the answer

claudiu06:10:43

@pvillegas12 @currentoor Been playing a bit with shadow-cljs + fulcro on nodejs. More of a *integration-ish* testing. But you can do in the browser tests or nodejs tests something like:

currentoor17:10:32

@U3LP7DWPR oh yeah that is pretty cool

currentoor17:10:35

thanks for sharing!

claudiu06:10:47

(let [started-callback (fn [{:keys [reconciler]}]
                         (prim/transact! reconciler `[(my-mutation)]))
      fulcro-client    (fc/new-fulcro-client 
                        :initial-state (atom {:your-test-state true})
                        :started-callback started-callback)
      mounted-app      (fc/mount* fulcro-client root/Root nil)
      reconciler       (:reconciler mounted-app)
      state            (prim/state reconciler)]
  (assert
   (get-in state [:your path])
   {:expected true}))

claudiu06:10:03

basically create a headless fulcro app, with the mutation in started-callback, then just check the state after the mutation.

claudiu06:10:06

should be pretty fast on nodejs, haven't done any performance testing for this approach. But you do get a lot with little work, and it masks the internals nicely. If you mock the networking think you could also get full stack integration testing with df/load & ptransact! using this approach.

claesenm12:10:25

Starting out with Fulcro but ran into a snag. I'm pretty sure it's related to the warning about ident's and link queries (http://book.fulcrologic.com/#_a_warning_about_ident_and_link_queries) ... I've got a join that seems to work fine based on the root component's query and initial state (both are fine), but upon actual rendering the join component's props are nil. It's exactly as described in the link I gave, but all my components do have idents and initial-state's that are being used throughout the tree, so as far as I understand it should have a presence in the db to prevent this problem from occuring. I'm at a loss right now ...

claudiu12:10:19

@claesenm any chance you can share some of the code ?

claudiu12:10:27

link_queries are usually for special cases most of the times you should have components with ident.

claesenm12:10:52

In my case I only have idents

claesenm12:10:05

I will put the code on pastebin since it's a couple of components, just a sec

claudiu12:10:17

🙂

claesenm12:10:02

A little messy (sorry!) but here goes: https://pastebin.com/cnWVuRLi ...

claesenm12:10:19

the state is structured as {:figures [[:figure/by-id xxx]], :figures/by-id {xxx {:db/id xxx :figure/layers [[:high-res-images/by-id yyy]], :high-res-images/by-id {yyy :{}} ... which seems to be fine, grabbing the initial state of the root component shows everything as I expect, but when I render ui-pixi-layer it's props are nil 😞

claesenm12:10:22

I expect stuff to be breaking in the PixiCanvas or PixiLayer component

pvillegas1212:10:57

@claesenm you mean this (js/console.log "pixilayer propz" props)

claesenm12:10:23

yes, those end up empty in the actual render

claesenm12:10:39

but the normalized initial state looks exactly the way I like, so the ident's seem to hold up there

pvillegas1212:10:35

try seeing what layers is here (map ui-pixi-layer layers)

pvillegas1212:10:43

it might not be a collection and instead a single value

claesenm12:10:19

it is a single-valued list in my test case, but normalizing a mock state also normalizes properly there

claesenm12:10:31

I'll see if that's the root of all evil

claudiu12:10:03

what's in you're state for [:high-res-images/by-id 1] ?

claesenm12:10:08

{:image/file-name "ITO.tif"
:canvas/width 500
:canvas/height 300
:viewport/x-start 0.5
:viewport/y-end 0.6
:image/base-url ""
:image/uuid "123"
:db/id 1
:image/degrees 0
:viewport/x-end 0.6
:viewport/y-start 0.5
:layer/type :high-res-image}

pvillegas1212:10:26

@claesenm your problem might be here

(merge {:layer/type type :db/id id}
             (prim/get-initial-state HighResImage {:db/id id})))

pvillegas1212:10:02

and

:query (fn [] {:high-res-image/by-id (prim/get-query HighResImage)
                  :blurb [:rubadubdub]})

pvillegas1212:10:11

the key has to align correctly

claesenm12:10:30

:high-res-image/by-id?

pvillegas1212:10:41

yeah, does the merge generate what you expect?

claesenm12:10:06

yes, but maybe I am expecting the wrong thing 🙂

pvillegas1212:10:19

normally, to have normalization, you would have something like

:query [{:high-res-image (prim/get-query HighResImage)}]

pvillegas1212:10:40

that is, in the db, you have {:high-res-image [:high-res-image/by-id 1]}

claesenm12:10:36

Ah, I see .. I thought I could solve that via PixiLayer's ident

claesenm12:10:05

(case (:layer/type props) 
  :high-res-image [:high-res-images/by-id (:db/id props)]
   )

claesenm12:10:32

but that might be a no no?

pvillegas1212:10:44

why would it have the same ident as the HighResImage component?

claesenm12:10:18

I'm not sure what would make a useful ident for a union component, the docs about unions omit them so I wasn't sure

claesenm12:10:34

This might be a moment of profound insight ... I thought I needed to place idents on all components

claesenm12:10:01

but I guess that's not necessary

claesenm12:10:47

for the union's ident I was freewheeling based on the fulcro book's example ...

claesenm12:10:57

(defsc PersonPlaceOrThingUnion [this props]
  {:ident (fn []
    (cond
      (contains? props :name) [:person/by-id (:id props)]
      (contains? props :location) [:place/by-id (:id props)]
      :else [:thing/by-id (:id props)]))}
  ...)

pvillegas1213:10:37

I think the ident and query are fine

pvillegas1213:10:24

Is this working for you

(do (js/console.log "Rendering pixi layer" props)
       (ui-util/conform-or-throw ::pixi-layer props "Invalid pixi layer in render")
       (case (:layer/type props)
         :high-res-image ui-high-res-image
         ) props)
@claesenm?

pvillegas1213:10:37

the () seem a bit off

claesenm13:10:00

You're right, those are definitely wrong. Not sure how that managed to slip by unnoticed!

pvillegas1213:10:30

that is responsible for rendering the res-image, does it show something?

claesenm13:10:53

still getting the same problem of nil props in the render of PixiLayer unfortunately

claesenm13:10:22

so I'm guessing the issue is higher up

pvillegas1213:10:43

what line are you using for debugging?

claesenm13:10:30

not sure what you mean, I'm using the figwheel dev setup of the fulcro template

pvillegas1213:10:52

Is it (js/console.log "layers" layers) ;; this is empty :-(? the one that is showing you nil props

claesenm13:10:10

it's not nil there, actually it's [{}] ... but everything downstream receives no props

claesenm13:10:31

the root props while rendering also show :figure/layers [{}], which I don't understand because the initial state looks fine as it normalized to what I expect

claesenm13:10:00

it's like that bit of state just gets eaten during render, while it is fine prior to that

claudiu13:10:43

@claesenm can you paste the entire state in a gist ? 😄

claudiu13:10:04

the pixi canvas has :figure/layers but in the initial state seems like just 1 entity... but in the render you do map

claesenm13:10:24

yeah that was wrong, I fixed that now but the problem persists ... collecting the state now

claudiu09:10:17

@claesenm Did you get to the bottom of it ?

claudiu09:10:48

Usually when I get into stuff like this I take if from scratch based on a working example and update if (the code you shared has to many working parts to debug from pastebin)

claudiu09:10:07

Noticed that in the book there's this example, that seems to do exactly what you want http://book.fulcrologic.com/#_demo_using_unions_as_a_ui_type_selector

claesenm10:10:13

I've currently moved this aside for a while but I am going to come back to it in a few days ... The example is indeed equivalent to what I'm trying to do. The weird thing is, I've never had problems with unions in Om Next, but now it turns out surprisingly tricky. I'm sure it's going to end up being some small detail, so I will try to bottom-up from the example you provided. In any case, I really appreciate your help and input, and hopefully I can fix this soon 🙂

claudiu11:10:23

you're welcome. Yep takes a bit to get used-to, both for writing and debugging. After a while it gets really easy. Gave up on om-next pretty fast, writing parsers for getting stuff out of the state....is just to much work for me, that approach seems quite brittle. prone to regression bugs. Think the design in fulcro with read-parser and conventions is as good as can be (one you get used to them)

claesenm13:10:56

The normalized db is as expected, which is why I assume all idents are working fine

claesenm13:10:59

I made a mistake copying the :figures/by-id in the normalized state to pastebin, but it has the right structure

hmaurer17:10:05

@tony.kay just found a (very minor) typo in the book: LocaleSelector vs LocaleSwitcher at http://book.fulcrologic.com/#_a_warning_about_ident_and_link_queries (end of section)

currentoor17:10:37

@hmaurer I think he would prefer a PR for minor typos simple_smile

hmaurer17:10:01

@currentoor is the book in the main repo?

currentoor17:10:20

yes, it’s one big ascii doc file

currentoor17:10:07

you could probably edit it in github

currentoor17:10:20

but it’s a very large file so it might a little slow

currentoor17:10:30

thanks! 😄

thheller17:10:21

React folks are so weird https://reactjs.org/docs/hooks-intro.html but it sounds kinda interesting

thheller18:10:56

react discovers binding and goes wild ... I like it 😉

thheller22:10:55

its all dependent on ReactCurrentOwner.currentDispatcher which is basically a binding in CLJS terms

wilkerlucio19:10:48

I wish they just stops complecting these things into the core, I think this one could be a separated library

thheller20:10:20

can't be a separate lib since it directly integrates into the react render reconciler

hmaurer22:10:02

it’s a strange API though, did you see the restriction that it can’t be called conditionally?

thheller22:10:34

yeah its using the call order index as a "key" to store the state

thheller22:10:40

very weird choice

thheller22:10:49

should have just taken a key argument instead imho

hmaurer22:10:52

oh is it? uh

hmaurer22:10:01

did you look at the implementation? I couldn’t find it

hmaurer22:10:44

using the call order sounds like a recipe for massive confusion

hmaurer22:10:52

unless they manage to give nice error messages about it…

thheller22:10:02

its implemented as a linked list so not actually indexed at all

thheller22:10:35

I'm less excited after looking over the impl

😄 8