Does anyone know of a React library that comes close to Fulcro's form state handling? Or more broadly, a React state management library that has the same normalized db + component query functionality? I'm reviewing another team's React codebase and it's infuriating seeing ad hoc "dirty" checking in each of their forms.
You can take a look at mobx-state-tree (https://github.com/mobxjs/mobx-state-tree), but its documentation barely exists and it was a pain to work with tbh. But they also have the concept of normalizing state, or at least, provide you the means to do so. You have to write a ton of boilerplate code. As you see, I'm not exactly a fan. I tried mobx-state-tree after finishing another project with plain MobX, which was nice enough. How you use it is entirely up to you. Before that, I've always written my own state management based on RxJS which kept things reasonably simple. Anway, long story short: You can give mobx or mobx-state-tree a shot, but in reality fulcro is lightyears ahead to every other solution I've tried over the years
Also Relay has a normalized cache for its GQL queries just like Apollo
Great, thanks folks!
I have not looked extensively at current evolutions. Apollo was trying. Not quite the same, but they are at least trying to adopt the normalization mechanisms.
@holyjak Thanks so much for the kind words! And I’ve very much enjoyed your blog posts over the years — I remember studying your dev REPL posts, and the one on incanter/gnuplot (long before I ventured to use oz!) Okay, I love the encouragement to stay in RAD — I’ll do some poking around tonight inside of it… Can you confirm that I’m thinking about this the right way, and have the arguments clear in my head?
(com.example.components.parser/parser {env} eql-query)
I think {env}
will be com.example.components.config/config
and eql-query
will look something like [{[:vimeo.user/id 118038002] [{:vimeo.album-list/data [:vimeo.album/uri]}]}]
Wow, if I could get this part running, I’ll feel AMAZING! 🙂OMG. It worked. 🤯🤯🙏🙏 > (parser com.example.components.config/config > {:address/id 1}) > => {[:address/id 1] #:address{:id 1}}
@tony.kay a small question about the future/commercial guardrails library you mentioned on a podcast: will it depend on clojure.spec or will the "spec'ing" library be pluggable perhaps? I was wondering about this, given the known flaw in the current spec version regarding "selection" context of specs (as discussed in the Maybe Not talk by Rich). What's your current perspective?
If you want to have a “paid alpha” program or something like that, count me in! 🙂 :thumbsup:
I’m hoping to have an early access program in the next month or two. There are a lot of little kinks to work out, and the CLJS support will probably be a few more months out from there (assuming ppl buy it, and I can afford to keep working on it).
Thx to all for the help running queries inside of Fulcro RAD, @holyjak @randumbo. Okay, now I’m having a problem with the session/get-all-sessions
resolver not being able to connect to the correct database (a Datomic Cloud instance, in addition to the in-memory db in the example.)
In my defaults.edn
file, here’s the databases I have configured.
:com.fulcrologic.rad.database-adapters.datomic/databases
{:main {:datomic/schema :production
:datomic/database "example"
:datomic/client {:server-type :dev-local
:system "fulcro-rad-demo"}
:datomic/prevent-changes? true}
:video {:datomic/schema :production2
:datomic/client {:server-type :ion
:region "us-west-2"
:system "datomic-2"
:creds-profile "default"
:endpoint "<http://zzz>"
:proxy-port 8182}
:datomic/database "videolibrary"
:datomic/prevent-changes? true}}
And here is my database query in com.example.components.database-queries
(defn get-all-sessions
[env query-params]
(if-let [db (some-> (get-in env [do/databases :production2]) deref)]
(let [ids (d/q '[:find ?s
:where
[?s :session/title _]] db)]
(->> ids
flatten
(mapv (fn [id] {:session/session id}))))
(log/error "No database atom for production schema!")))
I’m pretty sure I must have something wrong either in the schema name, or name of the datomic entry?
Hoping someone can show me what I”m doing wrong. Thx!!!thanks a lot for the explanation, Tony!
Your config looks correct on first glance. Maybe you just forgot to open the ssh tunnel to your cloud system?
Alas, manual queries work, so tunnel is working.
Is it okay for both :main
and :video
dbs to share :production
schema?
How does resolver know to look in video
db? (Manually examining the get-all-sessions
env
, it looks like it’s looking in :main
db, not :video
db…
Thx!
I guess ""No database atom for production schema!"" is the result you are getting?
Are you sure do/databases
should not be ::do/databases
, assuming (require '[com.fulcrologic.rad.database-adapters.datomic :as do])
?
Sorry, @holyjak, I forgot to mention!! I’m getting as a return value: []
That is when I have db entry set to production
(not production2
), and code in db query set to the same:
(if-let [db (some-> (get-in env [do/databases :production]) deref)]
OK, so your query runs but returns no data so you suspect it uses the wrong db.
Yes. (and all the other queries that work use do/databases
… I just copied/pasted. 🙂
I don't really know as I use SQL. There I need to explicitely tell it which DB to use:
data-source (get-in env [::sql/connection-pools :video])
Ooh…. looking…
Have you modified https://github.com/fulcrologic/fulcro-rad-demo/blob/master/src/datomic/com/example/components/parser.clj#L29 to add the second db?
Wow! Trying that now, and assuming I can have one for :main and one for :video. (crossing fingers!)
It seems you have not https://github.com/realgenekim/fulcro-rad-demo/blob/gene-experiments/src/datomic/com/example/components/parser.clj#L29 so I would expect (some-> (get-in env [do/databases :production2])
to return nil
What does it return?
(Can I have both :main and :video dbs share :production
schema? I’m hoping so, otherwise, I have to handle the attributes differently in com.example.components.auto-resolvers
.)
(Now it’s returning #:session{:all-sessions []}
. I think I’m getting closer? Still not sure if I need two schemas or not…. hmm…
🎉🎉
#:session{:all-sessions [#:session{:session 43518670227374203}
#:session{:session 54109166226112675}
Okay, so it works when I replace out the datomic/pathom-plugin
entry in parser
.
Is there a way to have two datomic databases, and if so, how?
Thx again, @holyjak!
(defstate parser
:
:
(form/pathom-plugin save/middleware delete/middleware)
;(datomic/pathom-plugin (fn [env] {:production (:main datomic-connections)}))
(datomic/pathom-plugin (fn [env] {:production (:video datomic-connections)}))
(blob/pathom-plugin bs/temporary-blob-store {:files bs/file-blob-store
:avatar-images bs/image-blob-
Perhaps this:
(datomic/pathom-plugin (fn [env] {
:main (:main datomic-connections)
:video (:video datomic-connections)}))
and in the code change to (if-let [db (some-> (get-in env [do/databases :main #_:video]) deref)]
the key in the datomic/databases
map and in the env
are completely arbitrary and do not need to relate to the DB schema, I believe
The version we’re working on “comes with” spec support at the moment, but we’ve put all of that behind a protocol. Hoping to support Spec 1, Spec 2, Mali, and whatever comes next in that arena. I’m aware of the problems, and that no single thing perfectly covers the bases at the moment.
A schema should have a 1-to-1 correspondence with a data store. You supply a function that figures out, for a request, which connection(s) should be associated with which schema. This allows you to shard easily, and even spread attributes among database types (Datomic could supply data for schema A, kv store for B, etc.)
I just happened to have this page open from the pathom docs, maybe that helps too: https://blog.wsscode.com/pathom/v2/pathom/2.2.0/plugins.html#_example_shard_switch
E.g. large strings are bad for Datomic, but you could set up a different db/connection/schema for those attributes and RAD can then save/load them to different stores. There’s a bit more work for you to do around that to make such a thing “atomic” to whatever degree you find satisfactory….RAD has no strong opinion on implementing two-phase commit for you.
Is the RAD concept of Schema identical to the underlying relational / Datomic DB schéma or is it a separate thing?
Regarding
> You supply a function that figures out, for a request, which connection(s) should be associated with which schema.
Where, how? Is that what the datomic parser plugin does?
The way I understand it, the datomic plugin inserts 1+ DBS into the env, each with a unique key, and I get-in env [.. the-key]
to get the one my queey/resolver wants. Do I misunderstand?
(I was thinking in terms of manual resolvers just as the one Gene was showing. I guess for the auto-generated ones it is indeed crucial that the Schema and DB key under env are the same so that they know what DB to use.)