This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-10-25
Channels
- # aws (1)
- # beginners (6)
- # boot (403)
- # boulder-clojurians (1)
- # clojure (28)
- # clojure-china (1)
- # clojure-ecuador (2)
- # clojure-ukraine (2)
- # clojurescript (27)
- # clojurex (5)
- # core-async (7)
- # cursive (5)
- # datomic (4)
- # hoplon (160)
- # ldnclj (2)
- # ldnproclodo (2)
- # lein-figwheel (2)
- # om (182)
- # onyx (1)
- # re-frame (1)
- # reagent (40)
- # spacemacs (15)
Is there something special that needs to be done when performing delete mutations? I have a list of items in my state and then I try to remove them all using a swap! mutation in the parser. The action succeeds and the state is updated; however, the dom doesn’t re-render until I perform another non-delete action (like adding a new entry)
Or I suppose more specifically is there a way to trigger a re-rendering. I tried using om/schedule-render! however it doesn’t seem to re-render until I interact with something that changes component local state (like a text box)
@sander, I had the same problem on one of the projects I was using for exploring om next. Starting a new one didn't have the problem indeed. Did you find out how to fix it?
@bbss no. one circumstance was that i was not working in the :main
ns i specified in figwheel.clj
, maybe has to do with that somehow
@dnolen thanks for the quick fix. with the same code, i now get this error: Uncaught Error: No method in multimethod 'scheduler.main.core/read' for dispatch value: :item-two/title
-> but why is om.next looking for a reader for this subquery? https://gist.github.com/ThomasDeutsch/ec80942bca3270013032
@dnolen sorry. i have seen your message right now - will check my code.
Still having a problem. After selecting another item, the old item will still get rendered. https://gist.github.com/ThomasDeutsch/141ba1d7c8691418869c.
@thomasdeutsch: I do not understand what the code you have written is trying to do
i tried to do this as simple as possible. i use two readers. Based on the result of those two readers, item-one or item-two will get rendered. I could use only one reader function, but can not see why this would be a better option.
Not that easy for me I can change the earlier gist, so that the result will not construct a map with the :one and :two keys. But then, it seems that the query in Root
is not correct - it will call the reader with {:one [...] :two [...]}
as selector but after a mutation, it will get called without the keys and only with one subquery. So, i changed the query to this: [{:selected-item [(om/get-query ItemOne) (om/get-query ItemTwo)]}]
. now i get this error: "No queries exist for component path (scheduler.main.core/Root scheduler.main.core/ItemOne)"
gist for the second case: https://gist.github.com/ThomasDeutsch/da3a1b8d88af2507e04f
@dnolen: and this is for the first case (query: ` [{:selected-item {:one (om/get-query ItemOne) :two (om/get-query ItemTwo)}}] ` ) https://gist.github.com/ThomasDeutsch/c8b0226de255b6b884d3
this is a necessity if you were going to for example query Datomic and needed to know which selector to apply
the problem is: after a mutation, the reader will not get the union query. it will receive only one subquery from one of the items.
i think it is because the query in my Root is not correct. It is this one: [{:reader-fn {:key [subquery] :two [subquery]}].
the problem I think is you’re invoking the switch from somewhere where the switch doesn’t actually happen.
but the child components are triggering the transaction (which is a bad idea in general)
thank you for this feedback! I did not now that it makes a difference what component will trigger the mutation, since everything will simply result in a db(state) change and i can trigger re-reading with the :value
param of the return map. i think it is time for me to get into the source a bit more.
it solved the problem ...
the fundamental issue is that children deep in the tree don’t have all the information
yes... ... it makes sense. it is like the standard react philosophy.
it would be nice if we could prevent this case, but’s of course impossible to know what a transactions means
i am so happy that i am able to help a tiny bit
@dnolen: last question for today: if transactions can only be called from the root - do i pass the callbacks down the tree?
In the Components, Identity & Normalization tutorial, in the section Studying Identity & Normalization/Adding Reads, the REPL code is producing a data structure where “Mary” loses her :age
key. Is this expected behavior?
should it be possible to return records from an om/next query? it looks like they are coerced to maps (https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L53)
feel free to file an issue - low priority for me probably until we get into the beta phase
no other thing I’ve used solves all these various problems I’ve encountered in UI programming over the last 10 years in one system
That’s great. I’ve really liked your transparency with the coding; and how giddy you get over it is pretty infectious.
Has anyone tried Devcards with Om Next? I am trying to understand how testing components with state works
@dnolen, the remote synchronization tutorial seems to be cut short. I'm probably missing something there and it was just meant to show how http caching can be achieved and the other parts will follow?
even if you cannot write super fast SQL queries you should still be able to write a lot of interesting applications without venturing from more standard backend choices thanks to HTTP caching
the point is that a much wider array of developers can leverage the approach without fear of messing it up
If a component's ident and query refer to a particular "object", e.g. [:person/by-name "John"]
, can you safely pass in (some-component {:person john :activate-fn #(...) :some-other-callback #(...)})
or do you always have to pass in (some-component john)
from the parent? I was wondering, since one may want to pass in callbacks etc. in addition to the "object" itself.
I guess ident would have to be implemented like this? (ident [this props] [:person/by-name (-> props :person :name)])
Actually, no, it only works with (ident [this props] [:person/by-name (:name props)])
. Perhaps ident
gets passed the query result during normalization? If I then want to pass in additional properties (like callbacks) in render
, (om/get-ident this)
will no longer work, since query result and properties don't have the same structure. Hmm...
@dnolen: Any chance to ensure (om/get-ident this)
passes the same data to (ident this ...)
as during normalization, even if the props passed to a component have a different structure?
@dnolen: Sure, I understand that. Is it a valid idea though to have a query like [:name]
, an ident like [:person/by-name (:name props)]
but pass in more than just the person to the component via its props?
(component person)
vs. (component {:person person :some-fn #(... perform a transaction or something ...)})
. I'm assuming the latter is incorrect given the above query and ident?
(And given a (defui Component ...)
and (def component (om/factory Component))
of course...)
I'm only asking because I'm wondering how to pass in more than just the query result to components. Like callbacks for instance.
you can never pass anything that isn’t in the same shape as the query (fixed my statement here)
How would you pass in callbacks to a component that defines a query? The callbacks are not part of the state after all?
Well, it queried data but that doesn't mean it doesn't also expect a callback to be passed in. It can't really include a query for a callback, can it?
But perhaps by "requested something" you refer to the structure and fields of the props passed in?
Yes. But what you've written in the tutorials doesn't ever pass in a callback (e.g. to perform a transaction in the parent component rather than the component itself), so I was looking for a way to achieve that. Turns out my attempt is wrong - I'm ok with that now that I know better.
@jannis I’m just pointing out that people often want to talk about two problems at the same time. I’m just trying to guide people asking only question at a time.
So 1) it’s never OK to reshape data in components. 2) adding more fields is fine (a component can’t ask for callback in their queries anyway)
Yeah, I noticed that's a recurring pattern today. (People asking multiple questions.) 😉
but will need to think about that, validation tends bring undesirable things when you want things to be more flexible
@dnolen: FYI your new doc on property-based testing refers to a snapshot version in the dependencies list.
1. I think it should be mentioned in the basic tutorial, that we should pass callbacks down from the point where the queries get constructed (the read functions are). i was using a flux architecture beforehand - and able to dispatch any transformation / action from any sub component, without using callbacks.
@thomasdeutsch: the problem is explaining something people aren’t ready to understand yet
the only reason is worked in flux is because flux doesn’t really have a discipline about how reads or how coordination happens
but in case anybody else wants to come up with some better suggestions … there are a couple of options worth hammock'ing
1) we could force subcomponents under a union to automatically lift their transaction to the union point
will do om.cursor 2.0 (transaction-cursors) (kidding)
3) remove components from being implicitly re-rendered if they kicked off the transaction
@thomasdeutsch: ^ this is kind of the source of the problem
if we never implicitly re-rendered you would immediately have to think about where you want the change to occur
OK, I’ll sound like the dense one…. On (3): why do we care if the component that kicked off the transaction gets implicitly re-rendered? Isn’t it cheap to do so?
but @thomasdeutsch’s case bring up a subtlety around unions
the children of a parent with union don’t see the union - they have their own specific subquery
if a child transacts, when parse executes it’s query (which is a more specific one of the parent one) you won’t see the same query information
this is a problem if you are using the query to make decisions which @thomasdeutsch was
will probably want to hear more cases like this before deciding whether this even a problem
I was under the impression that the entire UI tree query re-ran on each render, but that the list of things queued was used to optimize which things in the UI returned true/false from shouldComponentUpdate
When I read the code (and misunderstood it) I assumed since state it was in RAM cache, you were just assuming JS was “fast enough” for reasonable sized UIs. In a way I’m glad I’m wrong about that, but now I understand what you’ve been talking about with callbacks.
you wouldn’t want to rebuild data for subcomponents that aren’t on the re-rendering path.
Agreed…but that was at the root of a lot of my misunderstanding, because I had read the code for re-render, and missed the optimization. Thus I was continually puzzled as to why a transaction couldn’t just run anywhere.
and to be clear exactly what part of the tree we rebuild is definitely an implementation detail
we may figure out a way in the future to only rebuild a specific component’s data and avoid re-running queries
in some cases i used the datascript transaction-log to see what entites/attributes changed and updated accordingly.
@dnolen there's a missing closing paren at the defmethod form of read snippet in the property based testing tutorial