# om

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

joshfrench 23:21:18

i was surprised that om/computed clobbers any existing computed props, but i’m doing this within a union component so i may only be seeing the outlier case

dnolen 23:22:47

@joshfrench: there’s no particular reason for the behavior we could merge instead

joshfrench 23:26:10

ordinarily you wouldn’t pass down the complete props wholesale except in the case of a union or a pass-through, right? i’m trying to decide if it would be weirder to find inherited props in or to have to manually reconstruct them at every level

dnolen 23:28:29

well “inherited"

dnolen 23:29:03

I think it’s important to not abuse the feature

dnolen 23:29:20

accumulating stuff at each level just isn’t going to work

dnolen 23:29:35

and if you’re doing that be ready for very weird bugs

dnolen 23:30:18

for this reason the current behavior of clobbering maybe even the right one

dnolen 23:30:30

and we should just document it

dnolen 23:30:55

and people that want to play the dangerous game can do so knowingly

joshfrench 23:31:33

that’s my hunch, for all the cases where merging would be a reasonable convenience there are probably more where it’s a code smell

dnolen 23:31:54

k I’ll document the current behavior and we’ll see how it plays out

jannis 00:12:47

I could imagine merging computed to be quite confusing. Imagine A passing down a click-fn to a child B, which in turn has another child C that also allows a click-fn to be passed down. You could easily end up passing the root click-fn to both subcomponents by accident and weird things might happen.

jannis 00:13:48

If we don't merge, the click-fn will only be set in child C if it's explicitly passed down from B. I think at least for callbacks that's desirable.

jannis 00:13:56

Does this make sense?

jannis 00:15:56

I think it helps a lot if you have to assemble computed at each level. It'll be very explicit in each component, making it easier to understand what's going on.

dnolen 00:41:01

yes, I’ve updated the docstring to clarify the behavior

adamfrey 00:53:06

Does anyone understand how creating new Todos work in David’s om-next-demo re: Getting the datomic generated Todo :db/id attribute back to the client? I can’t find anywhere where todos/create-temp is being transacted

dnolen 00:54:37

@adamfrey: just never got around to do the temporary todo bits

dnolen 00:55:02

exercise left for the reader so to speak :simple_smile:

adamfrey 00:55:36

right, that’s where I am right now.

dnolen 01:00:39

yeah the problem here is the temp id problem

adamfrey 01:04:12

I have a thing that works for part of the problem. In my resource creation, I’m pushing into the list new item, but with an id of :temp, which renders it to the screen. Then I kick off the :remote true transaction

adamfrey 01:04:50

then my client reads the list again and I modified my parser to have this:

adamfrey 01:04:57

(defmethod read :places/list [{:keys [state selector]} _ _] (let [st @state] (if (contains? st :places/list) (let [places (get-places st selector) has-temp-place? (some #(= (:db/id %) :temp) places)] (if has-temp-place? {:remote true} {:value places})) ;; First pull {:remote true})))

dnolen 01:24:31

@adamfrey: yeah I thought about this some more I think this needs a standard solution

dnolen 01:24:55


dnolen 01:25:30

yeah this is too common a problem with remotes

dnolen 01:25:37

you need to be able to create temporary ident

dnolen 01:25:59

and then bang it when the real id comes back so that your database is correct

dnolen 02:14:26

@adamfrey your simple question had way bigger ramifications than I originally considered

dnolen 02:16:24

in a good way! :simple_smile:

leontalbot 05:10:33

Hello guys, hello @dnolen , so I took time to clean up a bit,

leontalbot 05:10:58

when I toggle first question radio button I get :

leontalbot 05:11:26

[ 11.488s] [] #object[votepourca.omnexttest.Answer] transacted '[(selections/update-radio {:value value, :name name})], #uuid "35d87a1d-a354-4dc3-9bea-967ab9c6e470" next.cljs?rel=1446568734541:905

leontalbot 05:11:29

Uncaught #error {:message "No queries exist for component path (votepourca.omnexttest/Form votepourca.omnexttest/Question votepourca.omnexttest/Answer)", :data {:type}}

leontalbot 05:12:02

And the mutation doesn't do anything.

leontalbot 05:13:05

Anyone? probably a newbie mistake but can't find it!

leontalbot 05:13:10

Thanks in advance!!

leontalbot 05:14:57

(Note: when I click a second time on any radio button, I don't get the error message, only the transacted trace, but again nothing changes.)

leontalbot 07:01:37

I updated the example

leontalbot 07:02:40

by adding a subquery :a -> {:a ~subquery} for answers in Question UI I don't get the error message ```(defui Question
static om/Ident (ident [this {:keys [id]}] [:questions/by-id id])

static om/IQuery (query [this] (let [subquery (om/get-query Answer)] `[:id :type :label {:a ~subquery}]))```

leontalbot 07:04:16

But the mutation doesn't work, and I loose my radio button props such as type or name so that I when I toggle a radio button, it changes in regular text input...

jdubie 08:09:26

i’m trying to build a simple example that uses om/subquery to fetch data for the currently displayed view. this seems very similar to @bplatz’s question about an idiomatic way to build up queries for only rendered components. Basically on demand fetching for only what’s visible.

the example linked to below has a mutation that modifies :route then renders a different component. at this point the repl shows the Roots query has been updated but it doesn’t re-render. i admit it seems dumb to have some state change, render, then render again because your query has changed because you mounted a child ref’ed by a subquery. however, directly changing the query directly isn’t a good option because i want an unrelated component to be able to update :route via a mutation and cause this component to render a different view.

interesting pieces from example here:

simonb 08:36:36

What's the right command to build om-next-demo?

simonb 09:47:05

I have an app which can be viewed in multiple languages (English/Chinese). So I store the current language in the Root view - in local state (initLocalState?). Or should that be shared? How do I ripple the selected language down to the child views? In props, query params, shared? Help! Thanks!

steveb8n 11:10:39

@leontalbot: I reported the same in an earlier comment. I think there might still be an issue with components 3+ levels deep but a simple solution is not to transact from the Answer component. Instead make a callback to a computed fn from Question. This should fix it.

steveb8n 11:11:13

take a look at my description from earlier this week for more details since there I used a slightly different fix

dnolen 13:24:08

@simonb: sorry don’t have time to explain how to get om-next-demo running. Sounds like you want to look at :shared which I fixed up yesterday. Not in a release yet though. You will need to install from master.

dnolen 13:26:16

@jdubie: example is too long for me look at sorry

dnolen 13:26:37

if people actually want me to look at stuff minimize it to the actual problem

dnolen 13:27:02

most problems can be described with about as much code as I use in my tutorials

dnolen 13:27:04

which is nothing at all

dnolen 13:28:02

@leontalbot: your example is also still too cluttered for me to consider

hmadelaine 13:28:23

Hello ! Is it me or there is a problem in the last Om-Next cut with the :shared and :shared-fn options ? There are optional but it fails at the expression : (when (contains? config :shared-fn) ((:shared-fn config) data)))

dnolen 13:28:50

@hmadelaine: hrm what’s the bug there?

hmadelaine 13:29:13

@dnolen Cannot read property 'call' of null

hmadelaine 13:29:31

(contains? config :shared-fn) returns true

dnolen 13:29:45

@hmadelaine: oops right

dnolen 13:29:49


simonb 13:31:42

@dnolen thanks. I'm reading the source. I think I have to use :shared-fn so can I change to reflect (say) a change of language. I think, :shared-fn gets passed props - props are immutable (right?). So, I'm just wondering how to get the change into :shared and how to propagate the change down to the children. Is this right or can I just use :shared (not use :shared-fn) and change the language key in :shared. Thanks!

dnolen 13:32:33

@hmadelaine: fixed!

hmadelaine 13:32:55

@dnolen: thanks !

dnolen 13:33:10

@simonb props are immutable values but that doesn’t mean they don’t change over time

dnolen 13:33:33

:shared-fn will run again if you change something at the root.

simonb 13:40:30

@dnolen can a component modify its own props? For example, the root component is inited with props indicating a language of English. Then the user selects Chinese, how should I get this change into the root so it ripples down to the children? Thanks.

jannis 13:52:18

@simonb:! is what you're looking for

jannis 13:56:29

@simonb: The root component gets its props via its own query. So you could have it query for [:app/lang ...]. The implement a read method for :app/lang and a mutate method for 'app/set-lang that changes :app/lang in the app state. Then, use :shared-fn (fn [props] {:lang (:app/lang props)}). When you want to change the language in your app (e.g. by clicking on a button), kick off a transaction like this: (om/transact! '[(app/set-lang {:lang "en"}) :app/lang]) (with ' = backtick).

simonb 13:59:02

@jannis thanks that's a big help. Is :changed-fn above :shared-fn ?

jannis 14:02:53

Oh, yes

simonb 14:11:12

So, props == query. Is this the same for all components? Does query always get added to props?

bplatz 14:15:29

@simonb Yes, if you implement it correctly it is. :shared and om/computed are ways to pass information outside of query if necessary.

bplatz 14:16:31

But beyond the root component, you are responsible for passing the proper props down to each component according to their query contract. There isn't magic in there that will do that for you.

jannis 14:23:43

@simonb: props = query result (your responsibility to pass down the results from the parent) + computed (for e.g. callbacks, stuff that is not part of the query)

bplatz 14:26:25

@jdubie I've been thinking about the best way to do this. I think ideally the router should handle modification of the query, and you sort of need the selection to happen outside of IQuery, as you want the query modified prior to it being passed to the parser. One idea is to use a key identifier for the route node components (similar to naming a interceptor in Pedestal, for example). If the query join in IQuery utilizes the same key, you could dynamically select the parts of the query that are relevant to the current route.

bplatz 14:29:18

But it is a problem I feel is necessary to solve, at least for my app, and so far the methods to do so feel hacky and confusing... so I'm still working on figuring out the best way.

bplatz 14:32:58

The method I'm describing would require a route component for each node in a nested route. You'd want the query joins to be exclusive of each other, and no other parts to the query except the mutually exclusive subcomponents.

dnolen 14:35:10

@bplatz: this sounds overly complicated to me

dnolen 14:35:51

if the queries are dramatically different and need coordination why even bother changing queries over just changing components

dnolen 14:36:17

in general it’s better to talk about problems so that they can be understood

dnolen 14:36:36

over whatever solution you’re mulling about Om Next and your interpretation of the solution

dnolen 14:37:13

it just makes too hard to understand if there’s something missing or whether it’s another documentation issue

bplatz 14:47:11

In the simplest of terms I can produce, the need is a nested data-driven router that only selects the bits of query that are relevant for the current route.

simonb 14:47:33

@bplatz & @jannis thanks. So, env in the read method of the parser is props? Or includes props? I'm trying to understand the query contract's relation to props on components. query returns a datalog expression, which gets passed to read, read also can access props for the component. Is that right? Thanks.

dnolen 14:48:09

@bplatz: right but I don’t understand why you need this - what problem is this solving?

bplatz 14:48:46

@simonb No, it is map that has the things you pass into it allowing you to get the props you need, based on the IQuery you declare.

dnolen 14:49:07

(this is an honest question btw, just trying to understand what actual advantage you are trying to achieve)

bplatz 14:51:56

@dnolen I come from the enterprise software space, so our apps have everything from analytics, workflow management, financials, etc. I simply want to ensure the entire app isn't loaded. The root component query, without further manipulation, contains everything the app could ever do.

bplatz 14:52:25

Some data sets are large, and if not needed I want to ensure they are not loaded.

dnolen 14:53:15

right so this is far into the category of things that Om Next does not care about and will never care about

dnolen 14:53:35

this is about a problem that you’ve constructed

dnolen 14:53:44

nothing fundamental

dnolen 14:53:53

that said ...

dnolen 14:54:10

I would not try to get this done with just the primitives

dnolen 14:54:34

why not provide you own root class thing over defui that automates all the bits you will need

dnolen 14:56:46

this is a problem I actually care about - are the Om primitives composable enough to accomplish higher level framework goals / abstractions

dnolen 15:01:55

@bplatz: another possibility is that you just want a delay primitive

dnolen 15:02:12

so you can just specify total queries and then force some part of the query to load

simonb 15:04:11

@bplatz: I think (from reading the om source) it includes [:state :shared :parser :logger]

bplatz 15:19:22

@dnolen: my own root class is what I proposed above as a router, it would manipulate query from the outside.

bplatz 15:22:41

A delay I think would be a nice addition, however for this particular case it may not be enough. Just the query graph itself could be significant, and it seems streamlining that to the relevant bits would provide more efficiency. But I don't really know yet, as none of this has been tried. :simple_smile:

bplatz 15:26:11

@simonb: Yes, and :state will contain your data, which you provide. I think a read through the wiki overviews is the best way to provide you context for this. I'd tackle that before reviewing source.

dnolen 15:26:11

@bplatz: sorry for not being clear

dnolen 15:26:22

I don’t mean root class as in the root of component tree

dnolen 15:26:34

I mean root class as in new component type

dnolen 15:26:57

a component type that knows how to be coordinated by the root

dnolen 15:27:09

in the way that you are suggesting

a.espolov 15:30:30

@dnolen: I have two questions for you.
1. No ideas how to use mixins let React with om. next, whether such a question?
2. Use of third-party components React?

dnolen 15:30:56

@a.espolov: not interested in mixins

dnolen 15:31:19

whatever people use those for, figure it out another way, protocols, specify etc.

dnolen 15:31:32

3rd party components should work fine

bplatz 15:32:38

@dnolen I think think more dynamism in IQuery would be ideal. Perhaps if you could also return a function with just :shared passed in, then you'd be able to put your route information into :shared and return just the parts of the query necessary. You shot down the idea, and probably for some reasons that are not clear to me, but in the interest of describing what could be a simple solution to me, that is it.

dnolen 15:33:30

@bplatz: right because you offered a solution to a problem I don’t understand

dnolen 15:33:54

in general not going to spend much time on feature ideas if I cannot understand the problem

dnolen 15:34:32

but I’m happy to work out what the real underlying problem is and come up with general solutions that cover a wider set of use cases

dnolen 15:36:38

@bplatz: I also do not even understand what you’ve suggested about :shared :simple_smile:

dnolen 15:38:00

but as long as thing keep getting framed in terms of solutions I suspect I will continue to have conceptual difficulties where I would like to be of some help.

bplatz 15:42:05

OK, that is a reasonable stance. I think the problem has been beat down enough and is understood, but please correct me if I'm wrong. I'm thinking in solutions now because I need to come up with one. If I think of any more parts to the problem or other use cases I'll send them your way.

dnolen 15:47:12

@bplatz: no I still don’t understand the problem at all

dnolen 15:47:48

because I’m struggling to find the underlying issue filtered through your current understanding of Om Next and the various straws you are grabbing at (which is fully to be expected)

dnolen 15:49:47

I also haven’t seen any code at this point :simple_smile:

dnolen 15:50:03

it seems you could write at most 30 lines of code to demonstrate the issue

bplatz 15:53:29

OK, I may just lack a better way of explaining it then. It is the ability to restrict the query graph to the parts that are relevant to the current UI state (or route). Same problem that Google Closure Modules solves for the relevant parts of your JavaScript code, which I've seen you produce great commentary about.

dnolen 15:54:58

so it just sounds like you want the root to be in control the query

dnolen 15:55:08

then why bother distributing it to components at all

dnolen 15:55:20

that seems to me root of all of your problems

bplatz 15:56:02

[{route-a-component (om/get-query RouteA)} {route-b-component (om/get-query RouteB)} {route-c-component (om/get-query RouteB)}]

bplatz 15:56:18

Only pick up one of the three.

dnolen 15:57:07

why bother with this?

dnolen 15:57:19

if this creates problems for how you want to build your app?

dnolen 15:58:19

absolutely nothing about Om Next says you have to build your query in this way - the docs just show the expected primary useage.

dnolen 15:59:03

as in why can’t the root have it’s own query building mechanism?

dnolen 15:59:25

it’s just data for whopping good reason

dnolen 15:59:35

there’s no syntax restricting you

bplatz 16:00:49

I want to distribute it to the components for the same value proposition you state for Om.Next. There is a lot of ease and power in the (om/get-query RouteA), which by itself is a nested query graph. The only thing is I just need one of RouteA, RouteB, or RouteC at a given time.

dnolen 16:01:28

@bplatz: you’re still missing what I’m saying

dnolen 16:01:37

you can put queries on the components

dnolen 16:01:47

but how you build the master query

dnolen 16:02:00

nothing prevent you from building the total query at the root for the whole thing

dnolen 16:02:08

and have the root component supply a filtering thing

dnolen 16:02:20

which walks the total query removing all the stuff that doesn’t matter

bplatz 16:03:54

Which is exactly what I suggested I was doing in response to @jdubie and you then stated I was over complicating things and henceforth this conversation.

dnolen 16:04:34

@bplatz: reading what you wrote that’s not the idea that I read

dnolen 16:04:49

but it’s easy to misunderstand

bplatz 16:06:35

I think if there is not a more native support of this sort of thing directly in Om.Next, then a router would take the responsibility of filtering the query, as it should know the route.

bplatz 16:07:18

By aligning routes with query components, i.e. /index.html = :route-component-b, then you could use those keys to filter the query nodes.

dnolen 16:07:23

@bplatz: we’re not going to add any routing abstraction like that. But also important to not create complications for those who wish to do so.

abp 16:10:14

isn't routing basically union? can be this or those components and i only render one?

dnolen 16:10:21

but based on your earlier statement - which again I don’t fully understand - there seem to be elements that aren’t needed (as far as I tell at the moment)

dnolen 16:10:36

I would not introduce routing components or anything like that

abp 16:10:44

sorry for coming with some hand wavy half knowledge shouting into you convo

dnolen 16:10:46

I would implement this simply as a filter on the root query

dnolen 16:11:11

but you may have determined a reason why this doesn’t work which you haven’t yet stated

bplatz 16:15:02

I mentioned a route component, yes. I thought there might be other logic required at a nested route node, but I was/am thinking through what would be required for my app.

bplatz 16:16:20

The component would be a simple reusable part that knew were to insert a nested route inside the dom/component tree, but that part is outside the scope of IQuery filtering.

bplatz 16:16:55

It was focused on render.

dnolen 16:18:20

Om 1.0.0-alpha15 released, includes some tweaks you can tire kick :shared and :shared-fn now

bplatz 16:18:54

@dnolen: no reason yet that it will not work, that is the path I'm headed down and I'll say something if I run into an obstacle.

dnolen 16:19:11

@bplatz: cool, sounds good

dnolen 16:20:25

@bplatz: off the cuff, the primary issue will probably be performance

dnolen 16:20:51

for this use case where the root wants to control the query it may be interesting to actually diff the query itself

dnolen 16:21:17

to figure what needs to change

bplatz 16:28:56

When considering a typical navigation structure, most of the differentiation happens near the root (your main nav). It is possible limiting the scope to just that is "enough" to reduce the query down, as opposed to having to be precise all the way down to the furthest leaf.

dnolen 16:31:17

@bplatz: right it might not be a perf problem at all.

wilkerlucio 16:32:14

@dnolen: talking about perf, do you think is suitable for apps with constant animations (like Musicoacher)?

dnolen 16:32:27

@wilkerlucio: yes

dnolen 16:32:59

being as fast or faster than React is still a goal

dnolen 16:33:31

“naive” React is what I mean of course

wilkerlucio 16:33:52

cool, thanks for info

dnolen 16:39:35

just released 1.0.0-alpha16

dnolen 16:39:53

included fixes so that remote integrate with DataScript is feasible

dnolen 16:40:04

i.e. transacting remote pulled entity tree (from Datomic) into DataScript

dnolen 17:05:01

also the last two releases include devcards integration

dnolen 17:05:15

it’s just a start but already pretty cool

dnolen 17:05:43

for example here are three of the tutorials as defcards

dnolen 17:05:52

makes it much simpler for me to see regressions at a glance :simple_smile:

iwillig 17:45:20

thats pretty cool @dnolen

dnolen 17:46:08

@iwillig yeah @jannis has already demonstrated how easy it is test components in isolation

dnolen 17:46:24

this gives you the beginning of reconciler mocking

dnolen 17:46:54

would like to get devcards history control hooked up here as well as better way to visualize the state

dnolen 17:47:48

but this is already a much better development / testing setup than I ever had in the past

jannis 17:53:09

@dnolen: I just pulled master and tried lein cljsbuild once dev. It fails with this error: Exception in thread "main" java.lang.AbstractMethodError: cljsbuild.compiler.SourcePaths._find_sources(Ljava/lang/Object;)Ljava/lang/Object;, compiling:(/tmp/form-init38129677347927342.clj:1:71)

dnolen 17:55:11

It depends on latest ClojureScript, you need to bump your tooling

dnolen 17:55:45

See the 1.7.170 announce

jannis 18:01:08

Would it make sense to bump the version of lein-cljsbuild in project.clj?

jannis 18:03:48

I've bumped that to 1.1.1-SNAPSHOT and now I get java.lang.AssertionError: No ns form found in /home/jannis/oss/om/src/main/deps.cljs. What version of lein-cljsbuild. Probably still missing something at my end.

dnolen 18:03:55

you need 1.1.1-SNAPSHOT

dnolen 18:04:12

make sure you clean your build

dnolen 18:04:45

that error makes no sense

dnolen 18:04:52

would need to see the stacktrace

jannis 18:05:17

Did that with git clean -xdf before running lein cljsbuild once dev. I'll paste the backtrace somewhere.

dnolen 18:07:12

@jannis just looks like a cljsbuild bug it’s trying to load deps.cljs for some reason

dnolen 18:07:14

no idea why

dnolen 18:07:34

I would report that to the lein-cljsbuild repo

jannis 18:07:46

Will do

jannis 18:23:44

Ah. Running lein cljsbuild isn't even needed to run the devcards. scripts/figwheel.clj is what I was looking for.

thheller 18:26:22

@dnolen @jannis that is in action

thheller 18:28:05

well, without the jar part .. but still a source-path seems to be wrong

thheller 18:28:56

deps.cljs must be at a source root, it will otherwise be interpreted as a normal cljs ns

thheller 18:28:58

which it isn't

jannis 18:29:35

project.clj looks a bit outdated. It still refers to "src/dev". And perhaps deps.cljs can go away and be replaced by an {:externs [...]} compiler option in the "dev" build.

thheller 18:30:16

@jannis check the source paths of your build

thheller 18:30:32

it probably contains /home/jannis/oss/om/src when it should contains /home/jannis/oss/om/src/main

jannis 18:32:21

@thheller: No, the cljsbuild build contains {:source-paths ["src/main" "src/dev"]}:

thheller 18:34:22

hmm maybe cljsbuild picks up paths from another target

thheller 18:34:28

the other targets still contains "src"

bplatz 18:35:45

FWIW, I was receiving a ICollection protocol error on alpha 15/16 and narrowed it down to me using the stubbed out :shared with an atom prior to you adding enhanced support for it. I bring it up because the stack trace doesn't do much to help isolate it the issue. An assertion for map? on whatever is put into :shared would have helped me, although with the enhanced support I would not have put an atom in there to begin with.

dnolen 18:36:19

wow lein is so annoying in this regard

dnolen 18:36:26

should be inclusions not exclusions

dnolen 18:36:35

anyways deployed 1.0.0-alpha17

dnolen 18:36:40

@jannis ^

dnolen 18:36:50

which removes all these unnecessary files

jdubie 18:38:14

@bplatz: here is an implementation of what you described. a) union query in the “routing” component and b) parse-time filtering of the query based on current route. a)

thheller 18:39:28

@dnolen the problem is probably that there are some build targets still specifying :source-paths ["src" "test"] which is incorrect

thheller 18:39:43

but cljsbuild gathers the all together when running jar

thheller 18:40:07

I see no reason why these files would be on there otherwise

jannis 18:40:17

@dnolen: It builds after making this change on top of alpha17:

dnolen 18:41:47

@jannis changing the :source-paths bit doesn’t make any sense to me

dnolen 18:42:08

it's superceded by jar-exclusions

jannis 18:43:46

@dnolen: It doesn't? There is no src/dev in the repo anymore, so lein cljsbuild once dev will fail, not finding it. I guess lein cljsbuild doesn't know about jar-exclusions?

dnolen 18:46:15

@jannis I don’t know what you are talking about

dnolen 18:46:31

if you’re talking about running cljsbuild commands from with in the Om repo

dnolen 18:46:40

that’s not something I’m concerned with at the moment

jannis 18:48:54

Ah. Yes, I am. They are still mentioned in so I supposed they are expected to work. But then again, the dev task is really not that interesting. The examples still build fine.

dnolen 18:49:42

@jannis yeah I’m pretty sure I’m going to convert all those examples into devcards

dnolen 18:49:50

how that’s handled today is very tedious and error prone.

dnolen 18:49:59

but that’ll probably happen after beta

jannis 18:50:49

Cool. I agree, that's a good way forward :simple_smile:

jannis 18:51:01

I'll shut up then :simple_smile:

flipmokid 19:34:48

Hi all, I have an app running with om next which works nicely without any optimizations. However when I stick in :optimizations :simple I get an error for one particular user interaction which says "Assert failed: (reconciler? reconciler)". Does this scream out user error? If so is there anything in particular I should be watching out for?

flipmokid 19:35:27

Apologies if this is in the wrong place or too easy to solve!

jannis 19:48:48

@jannis uploaded a file: Untitled and commented: @dnolen: Have you tried this? I might be missing something obvious but it looks like this always prints the current app state and applies the prev/next state in the reconciler when using the history buttons.

dnolen 19:56:33

@jannis yeah that won’t work you should read over @bhauman and I’s thread from a day ago in #clojurescript

dnolen 19:56:41

the state stuff isn’t going to work for Om Next

dnolen 19:57:06

@jannis if you have questions you should ask @bhauman I think he understands the issues pretty well

jannis 20:01:21

@dnolen: I skimmed through it yesterday or so. I thought one of the issues was the absence of a "history hook". I don't fully understand why but the above snippet seems to make that work. It probably swap!s the state returned by (om/app-state ...) and when defcard then rerenders the RootView (it calls the anonymous function whenever the card state changes), the reconciler has that state set. Not the cleanest way I'm sure but it seems to work.

dnolen 20:02:55

@jannis it really cannot be made to work with the state feature at the moment

dnolen 20:03:04

Om Next needs to control the root

dnolen 20:03:13

and if devcards is feeding it state the whole thing breaks

jannis 20:03:54

You mean calling swap! on the app state held by the reconciler breaks things?

dnolen 20:04:53

yes devcards listening on the state atom is just broken for Om Next

dnolen 20:08:58

not interested in hacking that to make it work either

dnolen 20:09:20

so we’ll probably need some kind of custom card - this is what @bhauman suggested

jannis 20:10:09

Hmm, ok. Both tutorial examples work with the above trick, including history, so I thought that could be the solution. Probably not then :confused:

leontalbot 21:38:17

@dnolen, ok now this is under 150 lines, maybe enough short?

leontalbot 21:39:09

the mutation does change the state, but the view doesn't update :disappointed:

leontalbot 21:41:33

@steveb8n Thanks! in the updated link, I do the transact at the second level now. Still the view doesn't update :confused:

jannis 21:43:33

@leontalbot: Move the :poll/questions out of the () in the transact! call.

jannis 21:44:18

[(selections/update-radio {:name ~id :value ~value}) :poll/questions] is what you want to pass in.

leontalbot 21:44:56

@jannis You did it!!

leontalbot 21:45:01

thanks a lot!

jannis 21:45:39


leontalbot 21:46:05

any other advices?

jannis 21:56:50

@leontalbot: Just minor things about coding style. Like: no need for apply in (apply dom/div nil (map question questions)) and perhaps (for [x a] ...) would be more readable than (map (fn [...] ...) a) in render of Question, could use more descriptive identifiers for answers than 1, 2, 3, 4, 5 (e.g. :not-interested, :yes-please) but the Om side of things look good to me.

leontalbot 21:57:53

Thank you @jannis !

tony.kay 22:26:21

@jannis: be careful about dropping apply with lazy in dev mode, not in production

scriptor 22:26:29

anyone know if repeated browser requests for favicon.ico and om rerenders might at all be related?

tony.kay 22:26:32

(from what I've seen on earlier, at least)

tony.kay 22:26:42

using mapv is fine, since it isn't lazy

scriptor 22:26:44

(this is in om.old)

jannis 22:27:57

@tony.kay: What do you mean by "dev" and "production" mode? Optimizations?

dnolen 22:38:36

hrm suprisingly neither Relay nor Falcor seem to deal with the temp id problem?

adamfrey 22:49:16

weird. Seems like nearly everyone will hit that?

adamfrey 22:51:38

or anyone relying on db generated ids, that is.

thheller 22:56:00

@jannis using the minified version of React causes different behavior in regard to lazy-seqs, some bindings uses will be incorrect which may cause errors

thheller 22:57:05

@jannis (doall (for ...)) or mapv like tony suggested prevents that

dnolen 22:57:11

@thheller: would like to see a reproducer for that

dnolen 22:57:27

I haven’t seen that in the any of the examples that I wrote with React with advanced optimization on

thheller 22:57:29

just include the minified version of react

thheller 22:57:34

and use a for

dnolen 22:57:40

already did that many times

thheller 22:57:43

or any lazy seq really

dnolen 22:57:43

no issues

dnolen 22:57:49

for loops, map etc.

thheller 22:58:01

I have only seen apply in your examples

dnolen 22:58:28

ah yeah you cannot return lazy seqs React doesn’t support that

dnolen 22:58:39

children can be an ES6 iterator

dnolen 22:58:45

but you must set this explicitly

thheller 22:58:54

yeah (doall (for ...)) works

dnolen 22:58:59

and Om doesn’t not expose this in any way at all

thheller 22:59:01

(for ...) does in dev mode

thheller 22:59:11

@dnolen no it works out of the box

dnolen 22:59:33

unspecified behavior far as I know

dnolen 22:59:49

unless you’re talking about this signature - and I have not seen this documented