This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-15
Channels
- # adventofcode (121)
- # bangalore-clj (5)
- # beginners (46)
- # boot-dev (9)
- # cider (20)
- # cljs-dev (7)
- # cljsrn (1)
- # clojure (341)
- # clojure-austin (7)
- # clojure-greece (144)
- # clojure-india (3)
- # clojure-italy (5)
- # clojure-spain (1)
- # clojure-spec (34)
- # clojure-sweden (3)
- # clojure-uk (90)
- # clojurescript (24)
- # core-async (1)
- # core-logic (7)
- # cursive (108)
- # datascript (2)
- # datomic (39)
- # events (1)
- # fulcro (225)
- # graphql (8)
- # hoplon (86)
- # instaparse (12)
- # jobs-discuss (2)
- # jvm (4)
- # keechma (1)
- # lein-figwheel (2)
- # leiningen (12)
- # off-topic (26)
- # onyx (35)
- # other-languages (1)
- # pedestal (3)
- # planck (11)
- # re-frame (12)
- # reagent (12)
- # reitit (5)
- # spacemacs (48)
- # specter (29)
- # sql (2)
- # test-check (1)
- # unrepl (71)
Hi all, is there any known gotcha for passing computed props to routers?
@levitanong havent tried, but curious what is the use case ?
@claudiu passing a google map instance down. Not doing that anymore, but still curious. When I was trying to do it, the computed props were nil.
pre-written routers don’t pass computed props through…they are two levels deep. It would be easy to do so, I just had not thought of it @levitanong.
@tony.kay Oh! Awesome.
Hey, I'm currently working with fulcro forms
and im trying to figure out what the way to go is with handling ui changes in a subform. it seems to be a bit of an overkill to rerender the whole form when for example typing in a subform.
The issue that I'm currently facing is that i want to call commit-to-entity
with the root-form when making changes somewhere in nested subforms
@timovanderkamp rendering is so optimized that you should never worry about that unless you see an actual perceptable problem.
not much “rendering” happens…just the changes. VDOM diff also is faster once in React production mode….so, should be fast
It seems to be a problem in Safari
oh im sorry, i mean form/set-field
I am passing the root-form as computed
to the sub-form and then call commit-to-entity
with that root-form
Are you using unions (routers) to make sure stuff that isn’t on the screen isn’t getting queried?
So if only the sub-form is being rerendered, the root-form wont contain the changes that have been made
ok, so some conceptual clarifications. The root form and subform each track their own changes through the normal entity props. Forms cache the original (from build form) state that was in your entities.
they are separate things…subforms (the concept) are so that the top-level form’s validation knows what other forms need to be checked when you ask globally “is this form valid?”
Do you have to do commit-to-entity
twice then if you create a new subform and make changes to it afterwards. One for the add-relation
operation and one for the entity-update
of the subform?
No I haven't read that yet
diff is smart enough to figure out all of the changes at any point. The lifecycle is here: http://fulcro.fulcrologic.com/guide.html#!/fulcro_devguide.O02_Forms_State_Lifecycle
If you have a set of forms declared, then running a diff (which is what commit does) will recurse into the subforms.
The forms support is really quite basic. It’s just a cache of the original state (from when you initialized forms) until commit (when the state is re-cached). Commit is just a diff of the two. Validation is just…well, validation on a specific current value.
The “current value” is always what is in your entity. So, the diff is between what you told it to start with, and what it is now. It’s up to you to decide when that is out of sync with respect to a server. For example, if using websockets, things get a lot more complicated, but you might also want to do optimistic concurrency where you carry versions along with entities to prevent overwrites on the server. The minimum delta support of forms is a way around that (last write wins is typically OK as long as a minimal delta of real changes is what is sent)
But none of that has to do with UI rendering speed….unless you’re doing more work than is needed. Most speed problems are due to over-querying in the UI….e.g. not using defrouter
to split up your screens.
What i'm currently doing is having a form which contains a list of subforms, if i add another subform - the root-form will rerender which is obvious. But whenever i update that subform i want to rerender just the subform, when saving this subform i want to call commit-to-entity
on the root-form (which i obtain by prim/computed
in the subform) and expect it to figure out all the changes that happened just like you said >diff is smart enough to figure out all of the changes at any point.
But because i only rerendered the subform the only diff it figured out was the add-relation
of the new subform. And not the changes made to the subform afterwards
I'm using a callback, but probably not the right way now i think of it.
ah i think i found my problem
on field blur you need to force a refresh of the parent form, so it’s props are updated
Indeed, or i can pass the subform to the callback, and compose it with the old state
yeah, the rendering refresh of the subform is updating its props, but the parent form has a cached version of those
Thanks tony for helping me out
Works smoothly now
So, note to general users. The defsc
messages are helpful, but don’t word wrap in Figwheel’s heads-up display. I’ve submitted a PR to figwheel, but until that is merged you can add this to your HTML file to get better error support when you make mistakes in defsc:
<style>
#figwheel-heads-up-content-area pre { white-space: pre-wrap; }
</style>
I’ve added that to the HTML files in fulcro’s lein template for 2.x and released it on clojars
@tony.kay I'm here on my journey for a generic error system implementation, I'm having just some difficulty to incorporate network errors on the process, I want ask if you have some advice on that, let me explain:
I'm using the ptransact!
to handle pre and post actions to mutations, the pre-action is to set some information on the entity to tell that a mutation is happening (kind like load markers), then I call the actual operation, and then I have a finalize operation, that checks if the result of the operation was success or error, and change the data according to it
looks like this:
(fp/ptransact! this `[(start-mutation {})
~(list mutation params)
(finish-mutation ~{:ok-mutation ok-mutation
:error-mutation error-mutation
:input params})])
this works fine for errors that come from the graph, done there
what I'm trying to handle now is the network errors on the same process
the problem is that I can't figure a way to handle the network error and get the context where the error happened
I was thinking about some options:
1. try to use tx-fallback: don't work because tx-fallbacks don't work with ptransact!
aparently
yeah, network error, like a 500, or server down
2. the global network error handler: don't work because at that point I have no idea what mutation or ref caused the problem
3. checking for network error on my finish-mutation
: not reliable, the only think I figure could be used for that is the global :fulcro/server-error
, the problem is that I might have multiple operations from multiple componetns running at same time, and that only shows what happened last
no, just one
the thing is, with network error you cannot know how much of tx ran, and how much didn’t
that's ok, I consider this a whole process, the problem is between ptransacts
wait, I'm getting confuse, what solution we talking about, 3?
ok, so, I'm doing a "localized" error handling
all error state goes into the ref that started the mutation process
for cases where the network gets there (and a problem happens inside of it), the normal flow works fine
the issue is when network failures occur, because I can't find how to associate that error with the ref
OK, so one thing is this: if the network is down, that is a global problem, not a local one.
I guess tx-fallback
seems the correct solution here, but its not working, I can double check, but I didn't triggered the handler last time I checked
yeah, but the opreation started from somewhere, and I would like to report it there
if possible
because that's where the user is looking at
so, fallbacks probably are broken in ptransact because the transform fails to understand them….actually, if you intersperse them in front of the remote they should affect, they might work ok.
For network errors though, I would suggest an overlay over the entire app letting them know the problem. That way you don’t pepper your entire app with fallback handlers.
I should try it more, I only did a quick one on that and fought they weren't supported
but since you say they should, I wanna try harder
So, the way ptransact works is it changes your tx. If there are non-remote calls (which fallback will look like), then it clusters those together until it finds one that is remote:
[(local) (local) (remote) (local) (remote)]
becomes:
1. [(local) (local) (remote)]
wait…. [(local) (remote)]
the fallbacks have to be on the tx they should handle, but they don’t look remote…so if you put them after, they’ll get mis-grouped
I do consider that a “bug” of a sort…not sure how those should be grouped for ptransact…should they all get copied to all?
yeah, seems like fallback
needs to be a special case if we want to support it
to be clustered with the remote instead of after
you mean like:
(fp/ptransact! this `[(start-mutation {})
(fulcro.client.data-fetch/fallback {:action mutation-network-error})
~(list mutation params)
(finish-mutation ~{:ok-mutation ok-mutation
:error-mutation error-mutation
:input params})])
humm, doesn't seem to work here
weird
I got this log [fulcro.client] Fallback triggered, but no fallbacks were defined.
what you mean it have start, fallback, mutation?
can you give me examples?
what about:
[(l) (r1) (f1) (r2) (f2)]
=> [(l) (r1) (f1)]
, [(r2) (f2)]
doens't sound weird that you replay all error handlers on all? I have no strong opinion on this, but I found it a bit counter-intuitive
the user/reader/developer coming after you should not have to read through all the mutations to figure out local semantics
I can't actually think on a case where I would want more than one network error handler per transaction, so, thinking on that the copy to all seems to make sense
if only (b)
is remote, it has one meaning, but if others are remote, it has a different one
I'm agreeing with your approach 😛
in example above: two different remotes…`b` and c
are remote, but you want to handle the errors from the remote for b
differently than c
This is a lib decision that has long-term implications…I’d rather play devil’s advocate a bit 🙂
1. implementation-wise it’s a pain to split that way. But that is me just feeling lazy 😜 2. Network errors are more of a global concern..the app cannot work when they are happening, but with multiple remotes perhaps you have a pretty complex micro-services thing where some things can just work while others fail.
3. Fallbacks are very fine-grained, and I don’t like them for that reason. The lead to lots of extra code…some on each tx. Seems very tedious. Errors should happen rarely, and peppering a lot more code around for something that rarely happens (and isn’t very recoverable when it does) sucks.
the fallback way I'm doing is something I'm only writing once
I'm kind creating a system here where I can choose if I want the operations to be optimistic or pessimistic
(per operation)
Fallbacks have their uses…don’t get me wrong on (3)…I just don’t like using them as a defensive tool all over the place.
also, like you said: wrap the logic in something else, and you never have to look at them
I see too many errors happening here, so I can't ignore, deploy is constant, and breakages happen more often than they should...
but I have to let the system users know it's currently broken, that's the whole point, but I'm not closed to the idea of reporting those globally, it's just that if I can report in the place where the user is already looking, I think that's a better UI
In a given ptransact!
:
1. take up until the first remote call.
2. Out of the rest, take as long as it is a fallback
3. 1+2 is next tx
4. Defer rest, (running is back through step 1)
I like that, this is how I was thinking when you suggested the clustering fix
because you look at the f
and now it's related to the remote just before it
1. Sort tx so that fallbacks cluster just to the right of the closest remote 2+ is like 1+ above
humm, I guess this is more prone to bugs, not against it, but I feel like it's ok to leave as user responsibility to place it right
I'm afraid that re-sorting might have unexpected consequences
actually, I don’t have to sort so much as re-do step 1 on the remainder and pull fallbacks out of that
you are the best, thanks man 🙂
@wilkerlucio try RC2-SNAPSHOT
Both of these specs now pass, so it should be good (and all prior tests still pass):
"Clusters prefixed fallbacks with following remote op"
(prim/pessimistic-transaction->transaction `[(fulcro.client.data-fetch/fallback {:x 1}) (r1 {:x 1})])
=> `[(fulcro.client.data-fetch/fallback {:x 1}) (r1 {:x 1})]
"Clusters postfixed fallbacks with closest prior remote op"
(prim/pessimistic-transaction->transaction `[(r1 {:x 1}) (L)
(tx/fallback {:x 1})
(L2) (r2)
(fulcro.client.data-fetch/fallback {:x 2})
(L2) (L)])
=> `[(r1 {:x 1}) (tx/fallback {:x 1})
(fulcro.client.data-fetch/deferred-transaction
{:remote :remote
:tx [(L) (L2) (r2) (fulcro.client.data-fetch/fallback {:x 2})
(fulcro.client.data-fetch/deferred-transaction {:remote :rest-remote
:tx [(L2) (L)]})]})]
very accurate 👏
trying it now 🙂
@tony.kay i implemented a datepicker as a fulcro component. is that something you'd be interested in packaging with fulcro itself, or does it make more sense to release it as a separate library?
@adamvh So, there may already be one packaged…I don’t remember. When it was Untangled, we had a lib called untangled-ui. I’m thinking of splitting some of the Fulcro lib off that way again. I don’t have time to maintain those bits, and they aren’t really part of the core mission. It would be nice to have such a spot for people to contribute into.
I combined it all for ease of maintenance, but I don’t like the things like bootstrap mixed in…there’s no reason to give it preferential treatment (or busy my life with UI tweaking CSS kinds of things).
@tony.kay tx-fallback been called with success 🙂
@wilkerlucio sweet.
@adamvh Looks like the old one got lost…I didn’t want to maintain the CSS for it, and like I said, not looking to maintain a UI component library. Don’t have time. That’s why bootstrap support is half-baked. There is also an image clip tool that was meant to turn into an image upload/browsing library. Part of that got lost in the shuffle from Untangled as well.
@adamvh How interested are you in joining in on a fulcro library as a maintainer??? 😄 Want to be the guy for fulcro-ui?
or you could package on your own…but the short answer is I don’t want to pull more UI components into Fulcro itself.
but I like the idea of having UI components for off-the-shelf use. It’s why I did semantic-ui-wrappers as well
they have controlled versions of a lot of things, so we don’t have to code/maintain our own
@tony.kay just one problem, no ref
at the fallback env =/
@wilkerlucio you and your refs 😜
they are vital for the way I'm generalising, but we are very close, I think this is the last missing one
I have a call at noon I have to prep for, so open an issue. Should not be that hard to add
is there a way to send params to fallback? just to see if I can keep progressing until we get that fixed
there are two special parameters: :action
and :execute
. The latter is used internally
humm, doesn't seem like it, the param for the fallback is just the map with :error
ah, so I need to send there
gotcha
it does
I was doing it wrong
new-children (->> children (filter (fn [child] (contains? symbols-to-find (:dispatch-key child)))) (map (fn [ast] (update ast :params assoc :execute true :error resp))))
I was adding to the original mutation params
@tony.kay not sure if you wanna change that, but I can't find a way to replace this component with a defsc
version:
(fp/defui ^:once CSS
static css/CSS
(local-rules [_]
(into [[:$pointer {:cursor "pointer"}]
[:$center {:text-align "center"}]
[:$right {:text-align "right"}]
[:$flex {:flex 1}]
[:* {:margin 0 :padding 0 :box-sizing "border-box"}]
[:body {:font-family "'Open Sans', 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif"}]
[:h2 {:font-size uc/font-size-18
:margin-bottom uc/space-5}]
[:a {:text-decoration "none"}]]
(helpers/gen-all-spaces 0 5 8 10 16 20)))
(include-children [_] components))
because it pulls the included children from a var, and the regular css is computed, defsc
doesn't accept that, and I think we don't have fn versions for the css, or do we? (I tried and got an arity error)
@tony.kay I just noticed an error been logged because I'm adding a parameter to a load-field
Error: You attempted to add parameters for #{:abrams.api/shard} to top-level key(s) of [({:>/credit-card-status-history [:card/id :ui/fetch-state :com.wsscode.pathom.core/errors {:card/status-history [:card.status-history/instant :card.status-history/user :card/status :card/status-detail]}]} {:abrams.api/shard "s0"})]
by this: https://github.com/fulcrologic/fulcro/blob/develop/src/main/fulcro/client/impl/data_fetch.cljc#L287
and this my code: (fetch/load-field this :>/credit-card-status-history :params {:abrams.api/shard shard})
this is totally legal, and I'm getting the correct response, can you clarify why this validation is there?
@wilkerlucio That error check is from the days of load-data
.
well, actually, it isn’t…the generic load is. See here is what you used to be able to do: run an arbitrary query, but you’d want to put params with the correct thing in that query…so it scans the query looking for the right AST node on which to place the params. The newer load code doesn’t let you do that (unless you use the low-level load mutation).
Also, NOTE, load-field
now allows you to use a map or named params…I assume you’ll be pleased by the former.
On your CSS. Read the error carefully. Arity problems mean it is supported, and you’re using the wrong number of args. this
is closed over from the arg list, so the lambda form of it is :css (fn [] ...)
This is in a comment in the docs, but I admit that could be better 🙂 http://fulcro.fulcrologic.com/guide.html#!/fulcro_devguide.M05_Defsc_In_Detail