This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-10-29
Channels
- # aws (1)
- # beginners (65)
- # boot (400)
- # cider (19)
- # clara (2)
- # cljs-dev (29)
- # clojure (127)
- # clojure-chicago (2)
- # clojure-conj (1)
- # clojure-dev (12)
- # clojure-russia (156)
- # clojure-sg (6)
- # clojure-za (1)
- # clojurescript (193)
- # core-async (23)
- # datomic (91)
- # editors (4)
- # editors-rus (1)
- # events (1)
- # hoplon (3)
- # jobs (1)
- # ldnclj (6)
- # leiningen (3)
- # nginx (3)
- # off-topic (5)
- # om (93)
- # onyx (10)
- # re-frame (11)
- # spacemacs (1)
- # testing (2)
- # yada (5)
@dnolen: Regarding path optimization: I modified @drcode's example to render two child components, one "normal", and one with a nil prop. Both components' (set-state!) trigger reads from the "wrong" parser route, but only one of them actually displays it. https://gist.github.com/thos37/934522181a68ca2f3b72#file-core-cljs-L53-L63
I'm sure this has come up a bunch of times, but what's the Om Next idiom for rendering a child component?
I think it's normal to define a shortcut to the factory. eg (def my-component (om/factory MyComponent))
and use that to render the component
yeah. create the factory once and use that. Otherwise you'll just keep making factories
the IQuery doc mentions âThis method should always return a vector.â but in Queries With Unions, DashboardItem
returns a map. is that okay because maps can behave like vectors, or doesnât (query [_])
always need to return a vector?
Is it an anti-pattern to use memoization in order to avoid allocating new objects? Itâs not that the memoized function in itself is costly, but it will help Om avoid re-rendering the child component.
Eg, I memoize (map :foo my-list)
which in itself is cheap, but allocates a new object every time itâs called (in render
)
The reason my child componentâs render
was called was that I handled an anonymous function to my child component, and (= (fn []) (fn []))
evaluates to false
.
@sander IQuery instances must return valid query expressions - this is always a vector except when you are returning a union expression (which is a map of query expression vectors).
Forgive a silly question: The Om-next quick start says "This component only declares one JavaScript Object method - render." So Object is a protocol? Where is Object as used in Om/ClojureScript defined/documented? I've grepped through the code of Om and ClojureScript looking for "defprotocol Object" but I can't find it anywhere. What am I missing? Thanks.
@simonb i think the name Object just refers to the generic javascript Object, and you can declare any method on your instance
@sander Thanks. So Object is not a protocol? The syntax looks like a protocol. But I think you're right. It's saying something like "this is a JS Object's methods" I'm just wondering where the semantics of Object are defined.
@simonb: i think this is just the design of the om/defui
macro. any function declared under Object
will added as a property to the instance (prototype)
@simonb Yes, all functions after Object become methods of the JS Object. You can define (foo [this ...] ...)
in there and e.g. call it from render
like this: (.foo this ...)
.
@simonb: defui
is basically deftype
and using Object
is a way to define instance methods on the type it creates
Ahh. I see. Thanks. http://clojuredocs.org/clojure.core/deftype
slight difference to clojure though since defining functions on Object is not possible there
OK, I have now created my first non-trivial Om Next project, will post it on github in the next few of days. I picked something that has a lot of cross-cutting concerns (a generic rectangle packing layout component) and the indirection enabled by the query selector approach made it surprisingly easy to implement (once I understood the design of Om Next well enough, which certainly required some effort)
@nolen: As you say, it's more a matter of novelty, not complexity. The bottom line is that any programmer creating a component first asks themselves "What does this component need to know about?" and the fact that previous-gen client libraries don't have a way of specifying this explicitly within components, via a DSL, adds lots of extra complexity in other libraries.
@drcode: yep I think as people get used to this model theyâll wonder they ever got anything done before đ
I'm playing with a little toy animation example in Om Next, and have encountered some odd behaviour that I suspect might be a bug. Here's a gist of a simple app that displays a button and a ClojureScript logo, and which makes the logo slide to a random location when the button is pressed:
It works. However, if I change the query in the (defui App ...)
form to include the animating?
key, it no longer works, even if I never use the value of the key anywhere in the component.
The code is a bit long, but the first 60 lines or so are not important. All you need to know is that the swap-animated!
function uses js/requestAnimationFrame
to modify an atom at every frame.
Yes, sorry about that. I haven't found a way to reduce the size. If it's not immediately obvious what is wrong, I can try...
No, I don't see any errors. But when I include that key in the query, the logo no longer smoothly slides to its new destination, it just jumps there.
@tord: please do, it could very well be a bug! would be nice to have a basic theory of whatâs wrong though.
OK, after some println-ing, I now know that the state atom is updated correctly at every animation frame and that the UI component's render
method is called at every update, but that the query does not return the updated results. Manually calling the parser inside the render method and printing the results shows the correct values, though.
(render [this]
(let [{:keys [x y animating?]} (om/props this)]
(println "rendering App: x: " x " y: " y " animating?: " animating?)
(println "parser result: " (parser {:state app-state} [:x :y :animating?]))
...))
rendering App: x: 0 y: 0 animating?: true
parser result: {:x 142.803804, :y 199.72560000000001, :animating? true}
rendering App: x: 0 y: 0 animating?: true
parser result: {:x 142.973312768, :y , :animating? true}
So the values returned by the queries don't match those obtained by calling the parser manually.
rendering App: x: 0 y: 0 animating?: true
props: {:x 0, :y 0, :animating? true}
parser result: {:x 271.592088, :y 289.433904, :animating? true}
And the strange thing is that when I remove :animating?
from the query, everything works, and the props are always equal to the result of manually calling the parser.
@tord hrm file an issue with the complete example ⌠I have a hunch whatâs going on but Iâm curious why changing the query would trigger this.
@tord part of the problem I suspect is that the reconciler uses a counter to know quickly whether props are stale
pretty sure thatâs the issue, and Iâm curious how your example worked in the first place to be honest
You mean that the app state should only be mutated directly from the parser, and that mutating it from animation frames messes things up?
banging on the atom from the outside w/o the reconciler being involved is something that should work - so itâs a bug for sure.
@dnolen OK, I managed to reproduce the behaviour with a much simpler app. Will file an issue. Thanks for your help!
@dnolen: David, I'm updating my overview docs, and I wish to make sure I've got this right: "for *queries*: the parser will only be invoked for either the top-level query, or starting at some node with an Ident". I'm trying to make sure people are not surprised at an entry into the parser at some other point that might jump into a read in an unexpected way. Am i missing anything?
(the prior versions says quite a bit about parsing...but just from a root perspective)
What is the effect of including keys defined by the read multimethod in the query expression of transact!
? e.g.
(om/transact! this `[(boards/activate {:ref ~ref}) :boards/active])
the :boards/active
part.
I got this from @jannis kanban app which I'm finding very helpful to look through 
@paulb: It tells Om Next to rerender components that query :boards/active
after the transaction.
@paulb: Initially, I thought the :value
part of what the corresponding mutate function returns would have that effect. Turns out that's only a way of documenting what keys are affected by the transaction. It doesn't have any effect.
yes, I had made the same assumption. imo would be helpful for the Om wiki to include an example of this.
how do you know if it's necessary to provide keys? In the Om wiki examples, components rerender without providing any
@paulb: I've updated the parser documentation: https://github.com/omcljs/om/wiki/Documentation-(om.next)#parser (hope @dnolen is happy with the explanation)
David said that when transact! is called on a component that component is implicitly included, so (transact! c â[(do/it!)])
is actually (transact! c â[(do/it!) ~c])
@paulb
I just updated my overview docs to fix my mutation misunderstandings. Relevant to the current discussion. Reading the Relay docs cleared up a lot of things. https://github.com/awkay/om/wiki/Om-Next-Overview It is a rough draft, but hopefully it helps people understand the "why" of transact, callbacks, and ":value as documentation on mutation".
New intro section covers some conceptual stuff, and the Mutation section was heavily revised
@tony.kay: The new introductory material is really good. I know it always helps me to have a motivating case in mind when learning something new. One typo: search for docuemtation