This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-16
Channels
- # aleph (2)
- # announcements (1)
- # aws (2)
- # babashka (5)
- # beginners (122)
- # boot-dev (1)
- # cider (3)
- # clara (7)
- # cljdoc (11)
- # clojure (161)
- # clojure-dev (45)
- # clojure-europe (8)
- # clojure-france (1)
- # clojure-india (1)
- # clojure-italy (3)
- # clojure-nl (11)
- # clojure-uk (34)
- # clojurebridge (2)
- # clojurescript (13)
- # cryogen (10)
- # cursive (13)
- # datomic (25)
- # emacs (8)
- # fulcro (76)
- # graalvm (2)
- # jackdaw (5)
- # jobs-discuss (2)
- # juxt (13)
- # off-topic (13)
- # pathom (5)
- # pedestal (7)
- # quil (2)
- # reitit (9)
- # remote-jobs (4)
- # schema (1)
- # shadow-cljs (33)
- # spacemacs (8)
- # sql (9)
- # vim (2)
- # vrac (2)
@slawek098 just assoc-in
it into state…it’s all maps and vectors. The normalized-state namespace has a few more helpers…but in general it’s pretty simple stuff.
for to-many on merges you can use the named parameters of a number of calls to merge methods, like :append.
There are also data targeting merge types. See the book
about to do some drag’n’drop things and I’m curious if there are any fulcro examples or suggestions? I’m betting this is a great use case for a state machine!
@thosmos so, I’ve done a bit of that…HTML5 does so much for you that it is really more about tracking real DOM elements and using refs from React
I ended up making a global atom to hold node id -> DOM refs so I could register the relevant DOM elements into an easy place to find them, so that I could do things like measure where I was relative to them on screen
I remember there being a bunch of crap you had to do for DOM purposes, but completely unrelated to Fulcro…read docs on HTML5 DnD very carefully is my advice…it was tricky to set up, but relatively easy to use
any experience with react-dnd from npm? It says it is a HOC pattern that injects props. I’m guessing I’d leverage the HOC approach from the guide if I were to attempt that? https://react-dnd.github.io/react-dnd/about Hmm, it looks a bit heavy, uses Redux internally … meh, I think I’ll start with doing it directly and see how it goes …
@thosmos you’d have to verify yourself but I think workspaces uses some react library to do it’s drag and drop stuff
Wow, that was easier than I expected! This article helped a bunch https://www.freecodecamp.org/news/reactjs-implement-drag-and-drop-feature-without-using-external-libraries-ad8994429f1a/
@thosmos I did use react d&d quite extensively on Workspaces: https://github.com/nubank/workspaces/blob/master/src/nubank/workspaces/ui.cljs#L649-L672
@U066U8JQJ thanks for the info. I spent a good amount of time admiring that very code last night. What makes it even easier to use is workspaces is already a dep via fulcro.
Hi, I need to refresh a page every second or so and I do that at the moment with js/setTimeout
when the component is rendered and this calls a mutation. This all works fine as long as the data is changing each time, that causes a re-render and thus a new timer being set. But when the data doesn't change on a subsequent call the component doesn't get re-rendered and the new timer isn't set.. and no more updates. What is the best way to address this?
How can I see to which version is fulcro book referring to? Because some functions mentioned here do not exist in most recent version, for that matter.
http://book.fulcrologic.com/#_using_integrate_ident merge/integrate-ident*
does not exist
@thomas If you really need an external source of events, then a setInterval at the top-level that does the data merge (via app) is better. Add in a UISM and you can use abstract events to control it and actors for UI elements to generalize it 😉…oh, and since UISM has timeouts you could skip the setInterval as well.
@slawek098 Sorry about that. I need to update the book, and it was not my intention to make any API disappear. I usually deprecate old names and point them to the new location.
When I try to integreate ident into list with
swap! state
(data-targeting/integrate-ident* [:wire/id wire-id] :append [:wire-list/id wire-list-id :wire-list/wires]))
I am getting error like:
core.cljs:159 ERROR [com.fulcrologic.fulcro.algorithms.tx-processing:348] - Failure dispatching optimistic action for AST node {:com.fulcrologic.fulcro.algorithms.tx-processing/idx 0, :com.fulcrologic.fulcro.algorithms.tx-processing/original-ast-node {:dispatch-key wires.mutations/add-wire, :key wires.mutations/add-wire, :params {:wire-list/id :my-wires, :wire/id 2}, :type :call}, :com.fulcrologic.fulcro.algorithms.tx-processing/started? #{}, :com.fulcrologic.fulcro.algorithms.tx-processing/complete? #{}, :com.fulcrologic.fulcro.algorithms.tx-processing/results {}, :com.fulcrologic.fulcro.algorithms.tx-processing/dispatch {:remote #object[wires$mutations$remote], :action #object[wires$mutations$action], :result-action #object[Function]}} of transaction node {:com.fulcrologic.fulcro.algorithms.tx-processing/id #uuid "15e89e41-e739-48ae-939d-9e7393f18c79", :com.fulcrologic.fulcro.algorithms.tx-processing/created #inst "2020-01-16T16:36:00.198-00:00", :com.fulcrologic.fulcro.algorithms.tx-processing/options {:optimistic? true, :component #object[Component [object Object]]}, :com.fulcrologic.fulcro.algorithms.tx-processing/tx [(wires.mutations/add-wire {:wire-list/id :my-wires, :wire/id 2})], :com.fulcrologic.fulcro.algorithms.tx-processing/elements [{:com.fulcrologic.fulcro.algorithms.tx-processing/idx 0, :com.fulcrologic.fulcro.algorithms.tx-processing/original-ast-node {:dispatch-key wires.mutations/add-wire, :key wires.mutations/add-wire, :params {:wire-list/id :my-wires, :wire/id 2}, :type :call}, :com.fulcrologic.fulcro.algorithms.tx-processing/started? #{}, :com.fulcrologic.fulcro.algorithms.tx-processing/complete? #{}, :com.fulcrologic.fulcro.algorithms.tx-processing/results {}, :com.fulcrologic.fulcro.algorithms.tx-processing/dispatch {:remote #object[wires$mutations$remote], :action #object[wires$mutations$action], :result-action #object[Function]}}]}
Error: No item {:fulcro.inspect.core/app-uuid #uuid "cafe0290-8a34-48ed-b16d-fd91ee130f6d", :com.fulcrologic.fulcro.application/active-remotes #{}, :wires [:wire-list/id :my-wires], :terminal/id {0 {:terminal/id 0, :terminal/connector "JST.0", :terminal/pin 1}, 2 {:terminal/id 2, :terminal/connector "SCREWED.0", :terminal/pin 0}, 1 {:terminal/id 1, :terminal/connector "JST.0", :terminal/pin 2}, 3 {:terminal/id 3, :terminal/connector "SCREWED.0", :terminal/pin 1}}, :wire/id {0 {:wire/id 0, :wire/label "Vcc", :wire/color "red", :wire/terminals [[:terminal/id 0] [:terminal/id 2]]}, 1 {:wire/id 1, :wire/label "GND", :wire/color "brown", :wire/terminals [[:terminal/id 1] [:terminal/id 3]]}}, :wire-list/id {:my-wires {:wire-list/id :my-wires, :wire-list/wires [[:wire/id 0] [:wire/id 1]]}}} in vector of length 2
How should I understand that?@tony.kay well, I think you're doing enough awesome work, there's no need to sorry 🙂
Thanks, but I complain quite a bit about how crappy the error messages are in Clojure, so I’m always trying to make it better, not worse. In this case, it could use improvement, which I will do right now.
I love the feel that Fulcro is like "top-down" framework for developing apps quickly.
The TX processing system runs mutations, and it crashed….it is telling you which node it was processing, which is a lot of info…should be a more concise error msg
original-ast-node {:dispatch-key wires.mutations/add-wire
is the mutation being worked onIs this generally good practice to manipulate state manually? Or should I use those helpers?
Wait, on server I need this "state management" only because I am not using any database.. OK, nevermind.
Is this regular approach to modify state on both frontend and backend? Like, I have both frontend and backend mutation resulting in essentially the same state on both frontend and backend
@slawek098 I would recommend you use good coding habits in mutations..the ones you use in every other programming language and program: things like readability, ease of maintenance, lack of complex code duplication, etc. I’d much rather see something like:
(defmutation complex-operation [params]
(action [{:keys [state]}]
(fns/swap!-> state
(wobble-the-mainstay)
(snarf-the-underworld params))))
than a bunch of individual integrate idents, etc.
Often, I’ll make a helper (for testing) called mutation-name*
(`complex-operation*` for the example above) (so there isn’t a symbol conflict), and write:
(defn complex-operation* [state-map params]
(-> state-map
(wobble-the-mainstay)
(snarf-the-underworld params)))
(defmutation complex-operation [params]
(action [{:keys [state]}]
(swap! state complex-operation* params)))
and then I have a super easy ref-transparent function of state-map to use in tests, and the mutation itself is always a one-liner.That also has the advantage of making the elements of the mutations (and even their sub-operations) reusable everywhere.
not sure I say that well enough in the book: The *
suffix notation is just a way to get around the fact that I already am using the base symbol as a mutation name, but want to make a separate implementation function with the same name.
Because I achieve the same effect by writing both backend and frontend mutations OR writing only backend mutation and reloading the page.
I don’t understand the question: are you saying you’re using a client-like in-memory database on the back-end? If so, you could put those helpers in CLJC.
Imagine I am adding new element to list. I've had frontend mutation adding element to list and executing backend mutation on remote.
So it feels like I am adding element to list independently on both backend and frontend.
ah, your choice: If you want fast UI experience, add them on front-end. if you don’t care about the speed, then you can do the latter: let the remote handle it and perhaps even return the type for auto-merge on change
not sure if there are specific examples that spell it out exactly that way, but all the primitives are well-documented
optimistic actions are always optional for full stack. You can always choose to reload your list after a remote operation (which you would code, for example, in the ok-action
instead of action
)
the optimistic stuff is about making it look instantaneous to the end user when your servers are a bit laggy
if you’re doing optimistic actions on front-end, then techically you should have an error-action
that reloads the list and probably shows a UI error…and you need to make sure your “definition” of errors is understood by the platform.
or you could have an ok-action
that looks at the network result, and do “softer” errors…
or you can be pessimistic and not do anything until it is done…at which point you still want error and ok actions if you want to be completely pedantic about it.
Another choice is probably more common: Make a global error handler that shows the error message and does something more drastic…and make sure the only way you get those errors is on really serious stuff (which is most common)….then your assumption is “errors are rare, this is a good enough user experience”.
@tony.kay Looking at the new keyframe-render2 stuff - how could we go about optimizing rendering when using state machines? Since you don’t call transact directly when modifying actors/aliases, there is no place to specify :update-only. Are you planning to add this? If not, I have a couple of ideas how it might work, and I could take a stab at it