This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-10-30
Channels
- # admin-announcements (11)
- # announcements (1)
- # beginners (1)
- # boot (247)
- # cider (15)
- # clara (16)
- # cljs-dev (14)
- # clojure (118)
- # clojure-czech (10)
- # clojure-ecuador (1)
- # clojure-japan (1)
- # clojure-russia (22)
- # clojurescript (57)
- # data-science (12)
- # datomic (2)
- # devcards (1)
- # editors-rus (2)
- # emacs (1)
- # events (2)
- # funcool (1)
- # hoplon (37)
- # juxt (1)
- # ldnclj (2)
- # leiningen (1)
- # nginx (12)
- # off-topic (16)
- # om (361)
- # onyx (34)
- # re-frame (3)
- # spacemacs (9)
- # yada (43)
when I switch from om.dom to sablano everything works until I remove the om.dom require from the namespace. Then I get Uncaught ReferenceError: ReactDOM is not defined
has anyone else seen this? the workaround is simple i.e. don’t remove the unused om.dom require
reactdom is from react 0.14, sablono is on 0.13, latest om alphas bring in react 0.14
I already have 0.14 (only) in my deps tree. I see what you mean about sablano using 0.13. I think you mean add another require to my ns to pull in 0.14
if that’s the case then I might as well leave om.dom in there for now since that works well (until sablano updates)
sablono 0.3.7-SNAPSHOT has the updated dep
Ha, this was fun. How about a really, really, really crappy drum machine built with Om Next? http://jannis.github.io/om-next-drum-machine/ 😉
@steveb8n: I've got [cljsjs/react "0.14.0-1"] [sablono "0.3.6" :exclusions [cljsjs/react]] in my deps and it seems to be working ok
hm anyone else having problems with willReceiveProps
? Sometimes it's getting called, most of the times not
I'm now abusing render
for my willReceiveProps
code because it's consistently getting called whenever state updates
When using react directly I only ever use it to fix some problematic behavior in a stateful component
in any way, even if I do it without willReceiveProps, I still have odd behaviour.
example: I am working on a editor. On every keypress I update the state with transact!
.
- I'm trying to change a state key from outside with swap!
- render
triggers successfully on my component
- (om/props this)
does not include the updated state field. Even consequent swaps is not changing that
- as soon as I do a keypress and transact!
triggers, the component suddenly receives the changed key that I just swapped from outside
ok so I got curious about this and tried to dispatch the transaction from my root component.
- created a async channel inside didMount
- on outside events, put the entire callback into the channel like so:
(go (>! root-channel #(om/transact! % `[(app/my-super-cool-mutation)])))
- go-loop
inside didMount
checks for these and executes the fn with this
parameters.
this is hacky as hell but gets around the problem. Now the render components receives the correct parameters right away
am I doing something wrong with my swap!
?@dvcrn How were you using swap!
outside the component? With om/transact!
? If so, you'll have to pass the keys to reread to the call like so (om/transact! reconciler '[(app/my-mutation ...) :app/some-key])
Only then will the component that queries :some/key
receive its new value via new props.
@jannis: with the latest alpha that's not possible anymore. transact is only for components that have queries
@dvcrn: I’m not sure about the future of willReceiveProps
we may just not support it - it exists to solve a React problem we don’t care about.
is it me or ? - I can't get the Components, Identity & Normalization example to work with 1.0.0-alpha12 -- "ListB" items are not updating (works fine till -alpha11)...
@dnolen: What do you think about allowing (om/get-computed this)
(where this
is a component) as a shortcut for (om/get-computed (om/props this))
?
It works nicely though, I used it last night. I like the separation of query results and extra stuff.
it’s of course also possible that components can be recursive w/o explicit recursion in the query like this - i.e. the recursion exists only in the component graph.
I've seen from the Datomic mailing list that there are recursive patterns which the Pull syntax can't represent.
E.g. when you have to step through more than one attribute to get to the recursive case.
@stuartsierra: right that’s what I mean by the recursion being present in the components themselves
oh, I see
@dnolen: No problem. I was just wondering. React had something similar with classSet
but they moved it into a community project (https://github.com/JedWatson/classnames). I find it almost too small to justify its own repository. 😉
Is it kosher to return singleton results in parsing functions, ala having a read function return {:value {:foo 22 :bar 33}} ?
@dnolen: not a form field, no. It's an editor. When a file is being loaded or saved, the backend sends a ipc message to the frontend (om). The receiver part is then calling transact!
. I tried the transact!
on the reconciler but got the "you can only use it if your component implements queries" error message
the query union syntax isn’t something Datomic understands natively, right? i’ll have to massage that in my parser?
i tried running the query generated by the tutorial:
IllegalArgumentExceptionInfo :db.error/invalid-recur-limit Cannot interpret as a recursive pull specification: {:dashboard/post [:id :type :title :author :content :favorites], :dashboard/photo [:id :type :title :image :caption :favorites], :dashboard/graphic [:id :type :title :image :favorites]} datomic.error/arg (error.clj:57)
@joshfrench: not supported by Datomic
you will want to write your query and then use the different pull selectors depending on what you have in hand
I wanted to make a snippet but it didn't suggest that on enter like it normally does. Oops!
Hi all, I'm playing around with om next. I want to have a page showing a list and a detail pane. I call my service at the beginning for the list which just contains the very basic data (say ids and descriptions). When the user clicks on an item I want to go off to the server and get the additional data (say id and body). I had originally thought that the list and the detail components could use the same data list, just with the detail component having a query param based on the id of the document it wants together with the extra properties it wants to display. Does this make sense? If so can anyone help me with what the queries should look like?
@dnolen: got it. thanks!
hrrm... now it's actually working. I must have mistyped something before otherwise I would have never done that async channel workaround
I think I am hitting the same problem as @joshfrench just described so I am expecting that "you will want to write your query and then use the different pull selectors depending on what you have in hand" is relevant.
I imagine datascript queries will be very useful when moving components around while making a windows metroUI-like card thing where the components are connected in complex ways
Is it allowed for the root component to be stateless, with stateful children, so that the root component just gets elided out for queries?
@drcode: The query has to compose to root....Root doesn't have to actually need any of that data itself
e.g. roots job would be to state what all of the children want, and then pick those pieces out and "pass them around" to the children.
David can possibly speak to where things might be going...but I know "multiple roots" isn't on the radar yet (which is what mutliple stateful children with separate query trees would kinda be)
so in deep recursive UIs you can only run the exact query a component needs and nothing else
Whats up with Warning: Each child in an array or iterator should have a unique "key" prop
?
@stuartsierra: that’s a react warning
@stuartsierra: a React thing
for when you have a collection of elements, React wants a way to identify them independent of the index
(to to disambiguate sibling nodes in the DOM - that is identify which DOM nodes are owned by which components)
@stuartsierra: the biggest issue if you don’t do this is that React can’t map component local state correctly
@dnolen: on path optimization.would you mind adding a little detail. I understand the localized query part rooted at an ident/ref, so you're suggesting we'll write a read dispatched on :read-ref that just needs to understand how to read an arbitrary subquery that is rooted at anything we've given an Ident?
@tony.kay: not really, you get ref (really ident) but you can’t really use that since at the moment you must return something that matches the query
but then your parse code will definitely complect declarative logic with optimization logic
Mmmm. This might be related...I've been pondering the issue of UI data being complected in with persistent data in the queries...lots of extra tease apart and put back together stuff I'm not loving there too
yeah, we were finding most cases could probably be handled with comp local state, prop passing, and computed...but then we move it out of app state and lose tracking
If my query expressions use selectors like [{:library/books [:book/authors]}]
do I need to do anything special in my read
function to handle it?
@dnolen: I'm trying to see how you'd work in the :value-like thing. Are you saying a parent parsing step would make the decision: "Instead of continuing down this parsing route, I'm returning this special :value-like this to indicate you should follow that parsing route instead"
every component that needs to update will have it’s props computed via defualt-ui->props
ok, so you're saying that if some threshold is reached, this function switches approaches away from full-query?
@stuartsierra: You might want to read my Om overview (see pinned items)...I talk about (the current) state of affairs with respect to implementing read in detail.
@tony.kay: I've been looking at that, in fact. That's partly what prompted the question.
your read function has to implement the "meaning" of that query. So I'm not sure what you mean about "doing anything special"
I think I'm confused because I'm used to Datomic Pull syntax.
Datomic Pull follows references automatically. Does the Om.next parser not do that?
@stuartsierra: not possible
I'm just using a local map in an atom right now.
@stuartsierra: however!
@stuartsierra: so if you use normalize
denormalize
you can get link following
OK. I'm using (om/reconciler {:state init-data-value :parser parser})
as in the examples.
@stuartsierra: and you looked at the normalization tutorial?
@dnolen: Yes, although I don't really understand what it's doing.
I can see my normalized data in the REPL.
so it takes a tree of data with dupes in it and converts it into a something that can be used more like a database - no dupes
you could of course avoid these steps but then you’re just pushing it server-side like Falcor does
I think I understand the rationale.
It's the details of the implementation that I'm struggling with.
@stuartsierra: like how it actually works?
yeah, or what I need to do to get the data back out.
@stuartsierra: denormalize
ahh, maybe that's what I'm missing
@stuartsierra: and note that my overview doesn't touch on normalization...all my stuff assumes you're using your own normalized data store (like Datascript). @dnolen: on path optimization, so you're saying on first render our read function returns a special :value-like that indicates "I can be updated by ref", so that future updates trigger the path optimization....or are we going to implement something declarative on the component that declares that support?
Oh, of course, query
has to ask for the keys that ident
needs!
Makes sense now.
So I guess if I want something like Datomic back-references :foo/_bar
I have to … build my own index?
@stuartsierra: yeah there’s no support for back-references at the moment
@stuartsierra: hrm, and really if you want that DataScript would probably be a better fit
OK, just trying to get a feel for what's easy and what's not.
@stuartsierra: yeah Om Next doesn’t have any support for real DB facilities
and to provide something pretty minimal that would integrate easily with a remote thing
couldn’t you get back-references by remoting to datomic on the backend? Doesn’t help with local cache but you could filter those keys through to the remote and away from the local cache (apologize for any naivety)
OK, that makes sense.
And if I did that (remote back references), then the Om.next normalizer would normalize them for me, right?
@stuartsierra: that’s correct as long as you’ve provided a proper ident to identify dupes
On optimization problem: ok, so once we've rendered the UI once we know the props that were used on each component. The assumption of Ident should be that the ident of a mounted component doesn't change over time (unless a parent query changes, in which case it would all re-render anyhow). The query is composed from there down and will change only in localized manner, so I'm still not seeing why the combination of "prior props run against Ident" combined with the subquery are not already sufficient...if you indicate (via docs) that the parser can be invoked at any point where an Ident exists I'm not seeing why you need an extra thing you pass to the parser. Are you seeing a way to optimize getting the data beyond trimming the query down to a sub-tree?
so why not allow a read on an Ident to return nil to indicate "no optimization present"?
That was why I was pointing at the "prior query result". It is the data. I was thinking we could tease what we needed from that
Maybe this is germane to this conversation, maybe not -- why does the normalization tutorial suddenly start making use of quoting and unquoting to build the query?
The reason isn't explicitly called out, but it's not (that) common to find it in cljs
@teslanick: quoting is just about getting the query into the API without having it interpreted by the compiler. Syntax can use () which would get turned into calls
ok. I obviously need to study the problem further, so I'll trust you on that for now. I don't want to waste your time teaching me the detail I'm missing. Given the assumption we have to get the user's input, then I like your proposal.
thanks for saying that. I'm pretty thick-skinned, but also am at the point where it is obvious more reading on my part would be more efficient
It seems like there are basically two kinds of options: the one you propose, and one where we declare something additional on the component itself. The latter seems to still need the former, so not sure what else you'd do.
@tony.kay: so I’ll write up everything we covered here and the options, Falcor context, and repercussions for DataScript vs. Om Next normalization etc.
that would be awesome. In the meantime I'm going to look at path optimization docs in Falcor
Made an Om issue for a new failing case I'm running into: https://github.com/omcljs/om/issues/453 - If anyone can see an error on my part in that example, let me know ASAP so I don't have to tie up dnolen's time
busted for the second time on build issues- Sorry, need to be more careful in the future
Having trouble troubleshooting an issue: Error: function (clearly a React constructor function) is not ISeqable
when attempting to normalize some data. I'm sure I'm misusing something somewhere, but I'm not sure where.
(om.next, attempting to adapt the normalization tutorial to a slightly different problem domain)
So do I have this right: When om/transact! is called, I am able to tell my program what paths are invalidated, by doing [(mutation! ...) {:INVALIDE-THIS ...} {:INVALIDATE-THAT ..}]
But I can't trigger an invalidation from within a mutation function (because the :value key is only there for documentation)
What I'm confused about is that when I transact from a deeply nested component, I have no idea what other paths are invalidated, especially if the component is a library component. But when I'm in the mutation function I have all this information.
Found the issue: It's expecting om/Ident
on a component that I don't anticipate needing it on.
Aha: [{ :current-planet (om/get-query PlanetDisplay)} ...]
=> [[:current-planet (om/get-query PlanetDisplay)] ...]
@teslanick: What difference does it make between using a Map and Vec?
Sweet. Low-effort validation with Om Next and http://thin.ng/validate: https://gist.github.com/Jannis/b4fc1c36a68e5bbef170
Not sure I like the idea to inject a new field into the card data just for validation but it's quick idea.
@drcode: You're tacking on "reads" to do after the mutation...the abstract is that you are saying "I want to change this, and I depend on this other stuff"..where "the other stuff" is a subset of all of the things that could have changed due to the mutation
If you;ve seen the "Fat Query" stuff in Relay, it's like that. There are dozens of things that your mutation could have changed, but only YOU know which of those your current UI needs to refresh
Think more in terms of the data exchange with a server as opposed to re-rendering...the re-rendering is the desirable side-effect...having the data correct in your local app state is the real goal.
(Just poking around at om.next trying to ge a feel for things. thanks tony.kay for your evolving doc too) From what I can tell using om/Ident means that om/transact! will include a :ref in the mutate env. That sounds handy for giving the mutate-fn the context but I don't see any examples of this in the documentation. I wondered if it's a good design pattern or not.
So, in my case, (:ref env) looks like [:person/by-name Anna]...
As a side-effect, two components with the same Ident are rendering the "same thing", so refreshing those components when a transact is done from a component with that ident makes sense: if one changed, then the other has changed as well.
Also, path optimization...work in progress...is part of that story. To be honest I'm still thinking about the other implications/flex points on Ident. For example, if you have a Car renderer that renders [:car 42], could you not also have a Vehicle renderer with the same Ident? Nothing breaks, other than the fact that the specific queries might vary in detail.
Yeah, that optimisation stuff is less clear to me. Having an "ident" for mutation context seems very useful though. Else there's a lot of boilerplate around passing a pk to transact! each time. I have one project where every table's pk seems to be a unique snowflake. Nothing is ID, many are a composite key. Keeping that complexity out of the way would be nice.
right, Ident has a lot to do with helping make sure all of the bits of UI that depend on the same (client-unique) thing update together
One other question: has anyone done a compare/contrast with the concepts from re-frame. Just curious since that's my reference point at the moment.
I'm probably focused more on how to manage business logic, REST api interactions, derived data etc. Possibly considered secondary issues for om.next just now.
David might have...I can say that if you read the Relay intro docs and a bit about Falcor you'll understand what om-next is trying to do
Okay, thanks Tony.