This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-08-10
Channels
- # announcements (2)
- # beginners (37)
- # boot (1)
- # cider (76)
- # clara (14)
- # cljs-dev (132)
- # cljsjs (1)
- # cljsrn (2)
- # clojure (18)
- # clojure-colombia (5)
- # clojure-finland (1)
- # clojure-hamburg (1)
- # clojure-italy (2)
- # clojure-nl (8)
- # clojure-russia (1)
- # clojure-spec (28)
- # clojure-uk (85)
- # clojurescript (84)
- # code-reviews (25)
- # cursive (10)
- # data-science (3)
- # datomic (30)
- # editors (1)
- # emacs (3)
- # fulcro (106)
- # graphql (4)
- # hyperfiddle (26)
- # jobs (2)
- # jobs-discuss (124)
- # keechma (3)
- # leiningen (1)
- # lumo (6)
- # off-topic (5)
- # other-lisps (5)
- # reagent (5)
- # ring-swagger (4)
- # shadow-cljs (140)
- # spacemacs (22)
- # specter (2)
- # sql (48)
- # tools-deps (78)
- # vim (7)
messaging works both ways
i think i’ll just use the websockets networking component, not make a headless client app
@wilkerlucio one of my builds shows No app connected.
in the fulcro inspect tab in the chrome extension, even though i see Installing Fulcro Inspect
in the js logs
i’m guessing something about my app is causing an exception in fulcro inspect, any suggestions for how to debug?
oh i guess i can just inspect it like a regular webpage
yeah there was an exception
Error in event handler for (unknown): #error {:message "No reader function for tag fulcro/tempid.", :data {:type :reader-exception, :ex-kind :reader-error}}
for some reason fulcro inspect is not loading the definition of fulcro/tempids when it tries to load
which versions are you in @currentoor?
"2.2.1"
in project.clj
it works fine for my other builds with the same dependencies
in the same project
the chrome extension is 1.0.2
yeah, versions are good
that sounds a strange issue, its suppose to have the fulcro/tempid set up
is your app doing some load at start? I just wonder if it is and you comment, we can check if it's some kind of network issue
are you setting custom networks?
yes it doing some loading at the start, the network is the fulcro websockets component
nothing custom, i’ll check
can probably be it, I never tried with websockets on network
i disabled both websockets and any load calls
this issue still happens
that's strange, where the error comes from?
i removed fulcro inspect from chrome and added it back
now it’s working
glad to hear
i can no longer reproduce the error 😅
that's the second time it happens, chrome seems to be corrupting files -.-
well at least we know this is something that could fix issues
what OS are you in?
macos yosemite
thanks, just trying to see a pattern, so I can compare with the next in case it happens
thanks for helping
Hi all!
I don't understand why I'm getting should have a unique "key" prop
on this code:
(def portfolio-snap-header {:share/name "Name"
:share/sym "Symbol"
:share/broker "Broker"
:share/currency "Currency"})
(def portfolio-snap-header-ks (sort (keys portfolio-snap-header)))
(defn portfolio-snapshot-header []
(dom/thead
(dom/tr
(vec (for [k portfolio-snap-header-ks]
(dom/th (get portfolio-snap-header k)))))))
(defsc PortfolioRow [this row]
{:initial-state (fn [p] p)}
(dom/tr
(vec (for [k portfolio-snap-header-ks]
(dom/td (get row k))))))
(def ui-portfolio-snap-row (prim/factory PortfolioRow {:keyfn :db/id}))
(defsc PortfolioTable [this {:keys [snapshot/rows]}]
{:initial-state (fn [{:keys [rows]}] {:snapshot/rows (if (seq rows) rows [])})}
(dom/table
(portfolio-snapshot-header)
(dom/tbody
(mapv ui-portfolio-snap-row rows))))
(def ui-portfolio-snap-table (prim/factory PortfolioTable))
(defsc ShareRoot [this {:keys [summary/portfolio]}]
{:initial-state (fn [p] {:summary/portfolio (prim/get-initial-state PortfolioTable {:rows [{:db/id 1
:share/name "Facebook"
:share/sym "FB"
:share/currency "USD"}
{:db/id 2
:share/name "Apple"
:share/sym "AAPL"
:share/currency "USD"}]})})}
(dom/div
(ui-portfolio-snap-table portfolio)))
(defcard-fulcro share-card
"# Full App"
ShareRoot
{}
{:inspect-data true})
I get it on PortfolioRow, because there's no :keyfn
there (btw, how do I do it here? tried ^{:key k}
but didn't work)
But what about PortfolioTable? Why doesn't it use the :keyfn
in the factory?
Thanks!PortfolioRow would need to have a query, and the query would need to have :db/id
in it, so that the :keyfn
can pick it up.
You don't have to use :keyfn
. If every 'detail' was rendered using a component that had a query and each query had :key
in it, and the value was unique by (gensym)
, then you would never get one of those errors. Not recommended of course - :keyfn
allows :db/id
or similar to be used.
TBH I don't know for certain :key
needs to be in a query, but I do know it needs to exist.
@cjmurphy Kind of. I watched the videos a couple of times and skimmed the docs. I definitely need to read more.
So, I got things working with queries. But I'm still seeing the warnings, but I think I now get what's happening.
I need to get a key to those td
elements. How do I do that? Pure JS?
anytime you have a collection returned react will warn you if there are not unique keys on them
yeah, I know in reagent is ^{:key k}
, and I tried that. Didn't occur to just pass as argument
Is there any good example of using fulcro with a datomic backend?
@pvillegas12 So the queries (for the most part) match Datomic pull….so for a given load, you can often just do a datomic pull. For schema/UI structure mismatches, I recommend Pathom as the intermediary
This YouTube video shows some pathom in the context of SQL (about 20 mins in), but it is trivial to convert the examples to Datomic: https://www.youtube.com/watch?v=gbrdnSsUerI&index=15&t=1619s&list=PLVi9lDx-4C_Rwb8LUwW4AdjAu-39PHgEE
I’m currently investigating a green field project with fulcro + datomic on the backend, any pointers @tony.kay?
Assessing the landscape, I’m fixed on Datomic as the backend. So for now I have clojure, clojurescript, react, datomic on my plate
ok, so the most important thing to understand is the unifying effect of the co-located UI query, and the (critical) join point functionality of pathom. Using Datomic gives you a boost because the graph query langauges match, but there is no real need to tie anything in Fulcro to a specific back-end.
Giving your UI components queries means you have to do very very little work (on the client) to read exactly the data you want from your server, and have it normalize into your client DB and refresh the UI. On the server, you need to understand how you code up the “mismatches” between what the client wants (UI tree structure) and how your db schema is actually shaped. When they match: perfect….`datomic/pull`. When they don’t, something like pathom/connect
, which is described in the above video. Wilker also gave a talk at Dutch Clojure Days about some more advanced and general concepts ideas…but the video will really give you a feel for that the server coding is like.
What about offline support?
Fulcro uses datascript as the underlying db in the client side right?
fulcro uses regular map dbs (they are much faster in the end then datascript for processing the query)
depends on how hairy you want to get. Fulcro does not use datascript, for various reasons I’ve talked about in the past
about offline support, pathom can build parsers on both clj and cljs, so one way to do it has having a local network that can target queries to some offline source (like indexedb or local storage)
I want to get really hairy at the offline support level
so, if you wanna go full offline, I suggest you can start with a cljs parser that fetchs data from indexeddb, and then you just sync it at some point with your server
datascript problem is that its not durable, and you have to load all in memory, that can get out of track depending on your content size
yeah, those work for small data sets, after that I think indexeddb is the way to go, so you can load pieces of the database
At the end of the day, it depends on what you mean by “offline”…your app can’t work unless it has all the data it needs, which implies you’re going to pre-query a load of stuff. Updates are a “hard problem” if there is any chance of concurrent access. You can cache them and sync them later, but they should probably use optimistic concurrency or CAS semantics in certain situations, which then makes recovery for the client a bit wiggy (how do you roll back something they did yesterday in the UI??? Well, you could use UI history…)
If what you mean is just “I want to tolerate network flakiness”, then that is much easier
Fulcro is optimistic by default, so you can code your network layer to just retry things on failures. The websockets support has an auto-retry feature for just that kind of mode
That can get you operation up to the point of needing a new query of data from the server
But all that aside: Fulcro gives you good isolation layers to make it as easy as it can be…it’s a hard problem that I don’t consider “part of” Fulcro proper.
I’m looking for the hard offline problem 🙂 that’s why I need something like datomic to be able to go back and forward to be able to solve concurrency problems
Datomic lets you view history, but it isn’t going to be easy to use that to “fix” conflicts in history.
yeah, I know, it has the proper semantics (I feel) to be able to resolve those issues
well, Fulcro will make hooking it all up simple…but it won’t solve your real hard problem, which is distributed disconnected operation. 🙂
yeah 😄
If you can prevent conflicts by design (e.g. no one ever edits the same thing at the same time), then it is trivial
From what I understood in the introductory video, it seems that I can queue up mutations I perform in the UI (assuming I have all the relevant data) and at some point in the future, when the user has a connection again, push all those mutations to the server
yes, that is simple…and the websockets support will already do that. The non-websockets stack would need retry code, which isn’t too hard
Perfect, I would start with a constrained version of offline (as you suggest). Thanks for the pointers, I would still need to serialize the db to something like indexdb right?
I’m designing a system that tolerates failures, and I use some of those elements. I’m also using CAS kinds of semantics to help detect collisions (mutations send what it was, and what it will be…but on conflict I’m letting user retry)
In Fulcro you can add any number of “remotes”, and queries/mutations can target any of them (mutations can target multiple). So, your writes could hit both local db and send remote. Return of mutation from server could help fix local db to match if there were conflicts.
Then leverage pathom to run the graph queries against that…again refer to the video for the idea
What is the om-next, fulcro story btw?
i can see how using datomic makes queries easy , but what about mutations? like if i've got a diff generated by form-state, what's the best way to turn that into a transaction back to datomic?
right now i just reshape it myself, but i'm curious if there's a better way , maybe pathom has some way to do it out of the box
@pvillegas12 fulcro 1.0 was just a library for om-next, but after some point it required more internal structural changes, while om.next tries to have a very open architecture (like open to pick which data structure you will use for local db, clojure maps vs datascript for eg), fulcro goes and takes some decisions for you (use the map db for example), and that made a case were fulcro cold run faster as fork then having keep compat with om.next
since then fulcro grew very fast and still improving on a regular basis
thanks @wilkerlucio 👍