This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-31
Channels
- # aleph (12)
- # announcements (4)
- # asami (7)
- # babashka (20)
- # beginners (92)
- # calva (74)
- # clj-kondo (8)
- # cljdoc (70)
- # clojure (47)
- # clojure-dev (29)
- # clojure-europe (27)
- # clojure-nl (7)
- # clojure-norway (3)
- # clojurescript (7)
- # cursive (2)
- # datomic (1)
- # emacs (8)
- # events (5)
- # fulcro (36)
- # gratitude (4)
- # humbleui (25)
- # introduce-yourself (1)
- # lsp (26)
- # malli (6)
- # missionary (8)
- # nbb (50)
- # off-topic (9)
- # pathom (2)
- # pedestal (3)
- # portal (32)
- # practicalli (5)
- # reitit (5)
- # releases (1)
- # ring (6)
- # shadow-cljs (87)
- # sql (31)
- # tools-deps (26)
- # vim (3)
- # xtdb (15)
Is there a way, in the browser, to use the cljs version of a pathom resolver, without any networking?
Yes, check https://fulcro-community.github.io/guides/tutorial-minimalist-fulcro/index.html out
hmm, I’m not seeing anything on that topic there.
Hm, can't find it now. There was a set of tutorial exercises, that had a premade, in browser pathom
"Exercise" was the keyword here https://github.com/fulcro-community/fulcro-exercises/blob/main/src/holyjak/fulcro_exercises/mock_server.cljs
this is pathom2, but should be easy enough to update to 3 https://github.com/wilkerlucio/pathom/blob/bb56c3ca00569b1b13353022a62209654470124b/docs-src/modules/ROOT/examples/com/wsscode/pathom/book/connect/mutation_async.cljs
https://github.com/holyjak/minimalist-fulcro-template-backendless is the one
Bit of a nebulous question, but does it make more sense to author the core
namespace of a project against the denormalized data structures, or against the normalized db common in fulcro? Say I go to implement some-algorithm
, should that fn accept a tree or a db? I'm sure the answer is likely "it depends", but I'm curious to know if others have given this some thought.
I'm tending to lean towards the denormalized tree for my current project. I like it's simplicity, but it can begin to break down at the points that entities reference each other (especially cycles or "back pointers", anything beyond basic map nesting).
Perhaps another way to ask this, do you consider the normalized fulcro table to be a core data structure when developing on the algorithms of your problem, or is it an implementation detail of the GUI that will eventually wrap that core? Would you include fulcro as a dependency in a non-GUI project?
Well, the reason that both are supported in Fulcro is exactly because the normalized form works better in some cases, and the tree-form works better in others. Normalization is critical for sane updates. tree-form is nice for things like structuring initial state or rendering a tree of components. If you’re writing a Fulcro application, you’ll be doing both. Context matters. In terms of your final expression of the question: Yes, the normalized database is a core data structure that I develop algorithms around. All helper methods of mutations, for example. A normalized database is absolutely what you want to be working against when modifying data. Form state, as an additional example, leverages the normalized concept into minimal diffs to great effect for distributed operation where multiple actors might affect the same entity in different ways over time. The tree-form is simply one of many possible views of the same core database. Thus the reason we put queries on components. The core database MAY have more data than you want to actually project into a tree. And of course I write many algorithms against these views (usually live in UI code). The most significant being the normalization itself, leveraging the component query tree with co-located idents so that you can write out a tree, and have a sane normalized db generated for you.
I cannot really answer if I would include Fulcro in a project that was not targeted at the web. I’m biased and all of my projects are Fulcro projects 😄
Thanks for the reply, that’s really helpful. So then do your core functions generally have a signature along the lines of (fn [db foo-id bar-id baz-id) -> new-db
?
By “core” I mean mutation helpers; the pure functions central to the domain of interest.
I can also imagine query helpers, (fn [db foo-id other-args]) -> materialized-tree
That general shape, of accepting a db and IDs, seems like it’d be common for top-level helper functions.
For context to my question, my goal is to write a programmatic interface for myself to tinker with at a REPL (or even use as a library), and then eventually wrap that interface in a GUI. So those core helpers would eventually become bonafide Fulcro mutations that swap on state, and UI components that extract trees for rendering. Does this development approach make sense to you?
If you are saying the following: “I’m going to write the data model and data evolution stuff first, then worry about the UI”, then I guess that is one approach. I generally recommend writing in CLJC because it does make a lot of things (including REPL dev) more convenient. I’m not sure about ignoring the UI to start: that is always going to lead to unexpected things later, but Fulcro is written to work in a completely headless mode, so you can certainly use every single feature to work up your data model before ever adding a UI, and you can ever use the core of Fulcro to manage that data model and then plug in your own custom rendering approach to deal with that UI.
Yea, ignoring the UI at the start is the approach I'm playing with, exactly. I agree it may not be wise, and I'm really just exploring here. I think part of the friction is that Fulcro seems to encourage me to consider rendering straight away, because those components are the drivers of the normalization goodness. I've been playing with raw components as a way to trick myself into thinking I'm not doing UI work, but really I'm just going to have to duplicate those raw components as defsc
at the end of the day anyway to render things (not interested in a custom renderer at this time).
So I suppose one way to look at it is that UI design drives the data modeling? Perhaps I need to broaden my view of UI to not just HTML/React, but just as a "general interface to evolving the data".
meh…I don’t remember where I did that…probably in several places…but yeah, you’ve got the point
Is the general idea to use empty defsc
forms in order to drive normalization? Because I figure, if I use raw components for my "data modeling only" functions to keep myself isolated from React, when I do eventually want a UI, I'll need to duplicate those ident/query specifications yea?
So, raw normalizing components have no React interaction at all. They also don’t track themselves in Fulcro component indexes, or support CLJ-style props. You technically could adapt them to have an acceptable render interface. But also remember that with React Hooks you don’t need a defsc
(components can just be pure functions), and the Fulcro hooks use-component
helper can be used to extract props using raw stuff.
Oh that's very interesting...so I could actually program without any dependency on React, and then use those same raw components to eventually populate the UI tree. I need to play with this a bit.
The raw components will work as a query source anytime you need props. You can add a watch to the state atom if you wish. Fulcro’s rendering is hooked to the transaction system, so a pluggable render is just a way to set that render hook (the function to call after a transaction completes locally or from a remote)
Gotcha, that's really cool. If I did just want to stick with stock everything (index tracking, renderer), I should use defsc
though. Am I understanding correctly? Rendering raw components is going to require extra legwork on my own behalf.
I suppose using both isn't entirely unusual. Raw components for my data modeling functions, defsc
for my web app, and the a different defsc
tree for, say, React Native.
Point being that having separate defsc
trees might not be something to fear. It feels like duplication, because I'm re-specifying the primary relationships within my domain in three places. The query/ident dance feels a lot like creating a schema, so I have a strong desire to keep it in one place.
it isn’t schema! That’s a really important facet. It’s a an expression of a desired view. Resolvers allow you to generate the fulfillment of data on demand, so the power of being able to simply say “I need exactly this data here” is the whole point. Yes, when you create a component that directly represents (primarily) and entity in your primary database it does make sense to give it an ident that has a one-to-one correlation with the backed entity; however there may be may facts in your query that come from disparate locations (lists of dropdown options, related info from other databases, etc). Fulcro’s database is intended to simply be a reified normalized database for the views in question. Yes, much of it may correlate strongly to real schema, but there is no requirement (or desire in my mind) for them to ever match exactly. That the whole point of having a dynamic system like Pathom that can do the work of joining together the data you want in the view without having to follow some strict schema.