This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-10-28
Channels
- # aws (3)
- # beginners (14)
- # boot (222)
- # cider (9)
- # cljs-dev (14)
- # clojure (107)
- # clojure-chicago (1)
- # clojure-dev (31)
- # clojure-nl (1)
- # clojure-poland (3)
- # clojure-russia (44)
- # clojure-sg (13)
- # clojure-za (3)
- # clojurescript (81)
- # core-async (5)
- # core-logic (4)
- # cursive (3)
- # data-science (3)
- # datomic (13)
- # events (7)
- # ldnclj (6)
- # leiningen (1)
- # off-topic (4)
- # om (298)
- # re-frame (13)
- # ring-swagger (7)
- # yada (12)
Yay. Added creating cards, deleting cards via DND, toggling card assignees by clicking on them in the card dialog to the kanban demo. It's all too easy.
Hi, I have a minimal example that generates an error that I don't understand: https://gist.github.com/drcode/0b4a2917b02b2c54c55b
This example has a parent and child component. If you press the button the parser complains about a missing read function
The problem is it wants a read function for a query tag that's deeply inside the absolute query, at which point it seems impossible for me to give a meaningful read function, since all context is missing
My impression was, read functions for the parser are by default only at the top level, unless you write a recursive parser. Therefore, this error seems to make no sense.
My questions: (1) Is this error expected behavior, or is this a bug in om next? (2) If it's not a bug, why is the parser parsing something ONLY when I call "set-state!"?
(The other possibility of course is that I'm still misunderstanding query functions and that is causing this error somehow indirectly)
(BTW: This is taken from a larger program that has a richer state structure and more meaningful read functions- I removed them from this minimal example, this is likely not the cause of the error)
I have a simple modified datascript om.next-tutorial here: https://github.com/thos37/om-tutorial/blob/master/src/om_tutorial/core.cljs#L48-L66 The Counter component has a query that returns an entity that is then wrapped in an atom, watched, and then handed to a reforms form that binds to the attributes of the entity. When the form updates the atom, the watch function does the om/transact!. Does this seem like a reasonable way to do this? It seems like this is a potential use case for a simple om.next/cursor-like-thing to wrap the 'path and transact function into something simpler that can be handed to the forms. Or would that be over-complicating it?
Are there any OM-like javascript clones you guys would suggest? I know, heresay, but alas not free to use clojurescript for this project
But in particular, I'm thinking well thought out cursor based central-atom style stores, as opposed to verbose flux style 'write a mutator for every change'
@snickell: guess you won't like it then that om.next completely gets rid of cursors and implements mutators for everything ๐
dvcrn: What I've seen of the reconciler approach of om.next seems a lot more DRY than the various flux libraries I've noticed
dvcrn: Just in terms of: "how many times does the name of this action get repeated" they seem rather verbose
hmm I'm still fighting with normalisation. I have the following :send
code (stolen from davids om-next demo):
(defn transit-post [url]
(fn [edn cb]
(.send XhrIo url
(fn [e]
(this-as this
(let [val (t/read (t/reader :json) (.getResponseText this))]
(cb val))))
"POST" (t/write (t/writer :json) edn)
#js {"Content-Type" "application/transit+json"})))
Person looks like this:
(defui Person
static om/Ident
(ident [this {:keys [name]}]
[:person/by-name name])
static om/IQuery
(query [this]
'[:name]))
but the resulting app-state is always empty after normalisation. :normalize
is set to true
. archive link to my previous post: https://clojurians.slack.com/archives/om/p1445939448003417could the issue be that (t/read (t/reader :json) (.getResponseText this))
returns a map with the keys being string? can that conflict with the normalisation?
seems like that was the problem. Changed my (python) server to return this instead (based on https://github.com/cognitect/transit-cljs/wiki/Getting-Started#reading):
test_data = {
"~:app/people": [
{"~:name": "David", "~:age": 22},
{"~:name": "Fred", "~:age": 29},
{"~:name": "Paul", "~:age": 20},
{"~:name": "Jiyoon", "~:age": 22},
{"~:name": "Bob", "~:age": 23},
{"~:name": "Mark", "~:age": 28},
{"~:name": "Jiwon", "~:age": 24},
{"~:name": "Dude", "~:age": 28},
],
}
now the app-state looks like this:
{:app/people [[:person/by-name "David"] [:person/by-name "Fred"] [:person/by-name "Paul"] [:person/by-name "Jiyoon"] [:person/by-name "Bob"] [:person/by-name "Mark"] [:person/by-name "Jiwon"] [:person/by-name "Dude"]], :person/by-name {"David" {:name "David"}, "Fred" {:name "Fred"}, "Paul" {:name "Paul"}, "Jiyoon" {:name "Jiyoon"}, "Bob" {:name "Bob"}, "Mark" {:name "Mark"}, "Jiwon" {:name "Jiwon"}, "Dude" {:name "Dude"}}}
should I contribute a wiki page how to use om with a remote server or is that better as a blog post?
@jannis Congratulation for your demo app ! Thank you for sharing
@dvcrn that's certainly a gotcha that more people will have a problem with, so I think a blog post should be useful until the documentation in the wiki has an om next FAQ / troubleshooting part
Hi @dnolen: in order to better grasp the big picture of Om-Next , I am studying Relay and Falcor. Do you have specific suggestion or reading the docs of the official sites will do ? Thanks !
Ok thanks
That's what I am watching right now
@dnolen: I am watching lana Kuenzel JSConf 2015. Do you have plan to provide optimistic mutation mechanism in the future ?
@dnolen: The error is "Uncaught Error: No method in multimethod 'example.core/read' for dispatch value: :bar"
So now I'm trying to understand why it is calling the parser against the inside :bar tag as opposed to the outside :foo tag (as it does during regular loading of the app)
(and whether calling the parser against the internal :bar tag is intentional behavior)
Is there any reason why
om.next/Ident
doesn't follow the naming scheme of other Om/Om Next protocols?@drcode: looking at your issue, I donโt see anything obvious - trying your minimal example now
Yes, that may have happened when I widdled down a minimal example- Is that issue triggering the bug or are the two unrelated?
Yeah, I know there's several different parts involved and I couldn't tease the intended behavior out of it- Thanks for the info, I will work around it with this new information!
@dnolen: FYI, when I try to correct the nil props I still seem to get the same error (Not expecting response on this comment, just an FYI for your troubleshooting)
Iโve encountered a browser-specific issue. Going through the Queries with Unions tutorial and the code in Putting It All Together is having intermittent issues where it beachballs with Safari 9.0.1 in 10.11.1. Chrome doesnโt seem to have an issue. Iโm trying to see if I can figure out how to replicate it reliably but itโs definitely happening.
Yeah. I just restarted Figwheel, reloaded the page in Safari, clicked any โFavorite!โ button, and it hangs for five seconds or so. After that, you can click freely except sometimes itโll hang again.
@snickell: http://omniscientjs.github.io/ sounds like what you're looking for. It's a javascript project based on Om, immutable data, and cursors.
@drcode also sorted out where to put an error so that you donโt run into these useless misleading errors
So, om-next can re-render leaf nodes (and can run a localized query if there is an Ident). I have an example where this leaf node wants to transact on the local state, but also has been passed callbacks. The local transact (on just the localized query state) causes the leaf to re-render (with an isolated query based on Ident), but now the callbacks are not available because the path from root wasn't the source of the re-render.
Not seeing any different behavior on alpha12 I'm afraid, no different error message... both with the version with nil props and there version where I tried to fix by giving proper props.
@tony.kay: Yeah, I'm guessing my confusion is around how om.next handles localized queries (even though I don't have an Ident) but I don't understand my confusion well enough at the moment to speculate more.
@tony.kay: Your example sounds like a great find though, exactly the kind of issue that will trip people up in the future
Well, David has said your example demonstrates a bug...but it was unclear to me what the bug is (passing nil as props?). What I ran into seems like a case where the approach needs some touching up, and might be related to the same thing.
Seems like for callbacks to be a "reasonable" approach, you need to render (at least) part of the path to that component...as far as I can see, it seems you need to render the path to the child (from root) to ensure that callbacks make it through.
I can, of course, "fix it" by including query keywords (to root) in my leaf component transact: (transact! '[(mutation) :parent-state-kw])
but the point is that specific mutation only modifies the "leaf"...so having to mention my parents breaks composition/isolation/local reasoning.
You're welcome...it is needing some corrections based on these latest realizations (I thought queries always came from root, but they don't)...but it also seems there is a bug related to that...so waiting for a resolution
The presence of Ident, in particular, makes it trivial to let Om re-render all of the components with the same Ident, and since Ident is supposed to be client-unique, it is trivial to supply a read that can find the state for the thing with Ident by running a new (isolated query). Unfortunately, this seems to break callbacks.
@tony.kay: Yeah the "queries not from root" thing is something I need to understand better
My docs are written (as I clearly state) with an incomplete picture of the inside of David's head
I remember when I was first learning CSS, my productivity over time was like 0%, 0%, 0%, 0%, 5%, 20%, %100, %100, %100... so basically a sigmoid curve with a very steep inflection point. Same thing with "om classic"... After I got the hang of it it was easy to be very productive
Now I'm still stuck in the "0% productivity" well for Om Next, but I can see the inflection point in the distance, can't wait until I finally reach it
I'm also stuck close to 0% for Om Next, but fortunately there is no hurry, as I'm already pretty productive with Reagent. I'll stick to that until I reach the Om Next inflection point.
@drcode: if you're not seeing a new error than you probably have something wrong with your build
@drcode: make a new failing example for me to look at once you've verified that's not the issue.
@tony.kay: you mentioned not wanting to add a parent key to your leaf's transact!, but I think you're referring to the query parent. As you said, the render tree needs to exist to that leaf for its callbacks to work. So I think I'm hearing you almost saying that there could be a way to traverse the up the render tree from the leaf in order to make the query tree work?
@tony.kay: this highlights something I've been wondering about, but haven't done enough experimenting yet to answer for myself, so I'll wonder aloud for now: Could there be a way, by following the render tree path back from any leaf query to a parent query, to be able to assemble a root query automatically (without needing to explicitly describe child queries in the parent query)?
@dnolen: Sorry, was a build issue. Needed to force a clean js build. Everything now appears to be working 100% on my end with Alpha12
yeah, plus if there's no direct query dependency between parent and child, then for all intents and purposes they're not really parent/child in the query sense, only in the render sense
@thosmos: The way the Om Next approach (potentially) decouples the query hierarchy from the dom rendering hierarchy is really interesting to me.
and reverse traversing the render tree from leaf to root in that situation to re-run the root query with only the changed bits is _? It seems like knowing (or being able to decipher) the render tree path from any om.next/Ident component could be useful for the indexer to know how to run just the changed leaf's query all by itself and to know to only trigger a render on it. But again just I'm wondering aloud at this point as I haven't done the research yet.
@dnolen: (on bug fix): Great, so it does not require rendering the path from root, I take it. Merging non-query props?
so the fundamental problem is that everyone is trying to put computed properties along with props that go along with queries
move reads up, duplicate logic (in the case of path optimization youโd have to reconstruct this information since you canโt get it from the parent) etc. etc.
dealing with metadata directly is annoying of course so we can just provide a simple helper
now when you change something with Ident, the other components can rerun their queries and also just copy over computed
Questions/suggestions: 1. Have you considered implications of closures over parent? (Not saying anything is wrong...just noting a potential place to analyze) 2. Perhaps add that to the generated factory instead of requiring additional calls?
If the thing in metadata closed over something in parent, and you cache it in metadata
if youโre copying something over the closure canโt possible matter since you got it from the parent
so it's like a component level persistent state store that only exists until the parent rerenders?
but itโs just a mess when youโre trying to do this super functional thing that Om Next does
the big tradeoff is that this stuff isnโt visible at the REPL, will need tooling to see this information
orthogonal concerns leans me towards metadata, but visibility leans me towards keyword
ok going to go w/ special key om.next/computed
om.next/get-computed
unless I hear something better in the next 5 minutes while I code this up ๐
I think the concept is sophisticated enough that people will be helped by just being able to (print (om/props this)) and see that there's some special stuff in there.
so it seems like we would need to use key or metadata depending on which one is appropriate
@thheller: You can always write your own helper function for that (I keep annoying David with the same kinds of suggestions ๐ )
@tord: re: your earlier question around naming of om.next/Ident, there is om.next.protocols/IIndexer ๐
@dnolen: is there any chance of wanting a (defrecord Ident) in the future and then needing to name it something different because of that?
Ident is nicer on the eyes when getting started and especially for how commonly it's used
GraphQL: types, coercion, and introspection...bleh...it's like reading about lions and tigers and bears.
Did I read earlier that select-keys
is a bad choice for extracting query results for subcomponents? Example: [{:persons (om/get-query Person)]
-> (let [persons (select-keys (om/props this) [:persons])] (person-list persons))
doing it as an implementation detail in your read/parser are fine, since the computed stuff is applied after
but implementation detail, so orthogonal to the real point: don't enforce query logic in the UI...which hopefully is obvious
I'm not sure how the select-keys
example above is any different regarding what it expects than, say (get (om/props this) :persons)
... you have to do something like that to extract the props you pass down to children, no?
@jannis: that would be fine, in that you're not changing the query result, and you'd still explicitly pass the computed stuff you wanted to pass on to a child. The point is you should not be "filtering" out stuff. Picking a sub-result to pass to a child is fine. It was a pretty narrowly focused example where I was trying to explore where pass-through might accidentally filter out the "computed" data and surprise a developer.
well, don't really molest the query result at all...getting the response "right" was the parser/readers job.
@dnolen: how does the om/computed enhancement address @drcode's example from earlier (https://gist.github.com/drcode/0b4a2917b02b2c54c55b) in which a subcomponent is rerendering itself on a set-state!? Is om going use the computed mechanism to store its previous state and avoid doing another query read?
@thosmos: set-state causes a re-render of a leaf node, and parent "stuff" is lost in the old model, I think...(to be honest, didn't look at that example)
in drcode's situation, a query read on key :bar is happening on Child's rerender, even though there is no read fn for that key defined and Child has no Ident.
oh i see, his example isn't working because he didn't pass a prop for that key, which would be stored by this computed change?
Sorry to pollute the chat, but I saw someone posted in here how to configure the reconciler for react native and I canโt for the life of me figure it out. Unfortunately it looks like the search goes only so far back and its lost in the history. Does anyone know what to pass in for :root-render and :root-unmount for react native?
@tyler: they wrote a blog: http://dvcrn.github.io/clojurescript/react/2015/10/27/going-native-with-om-next.html
I'm going to echo David's (implicit?) recommendation: Read the Relay docs. I'm embarrased to say I've probably cost myself many hours of head scratching by not just reading the pages at https://facebook.github.io/relay Particularly "Thinking in Relay" and the Mutation page under "Guides"
Dumb question, and maybe it's already been answered, but what is the proposed way of adding something to a normalized collection?
I'm going through the tutorial pages (just finished 'Components, Identity & Normalization') and was thinking of extending it to add a new person either to one of the lists.
you can call om/normalize on the data you want to insert and then merge that into state