Fork me on GitHub
#om
<
2016-09-06
>
jimmy02:09:39

@tmulvaney you can also do this (swap! app-state assoc :foo :bar :foobar :baz)

mitchelkuijpers11:09:12

Has anyone ever had om removing data that you are still using when you are doing a lot of updates? I have a autocomplete component that searches for items that have an ident of [:entity/by-id z] and I have three other collections with items that also use the same idents and when i start searching with the autocomplete it will start removing items that are rendered in the ui… Am i doing something wrong?

mitchelkuijpers11:09:18

When I run (om/ref->components reconciler [:entity/by-id 17592186045752]) For one of my indents it will first have one component and then after an update from the autocomplete (which goes to a remote) it will return nil

mitchelkuijpers12:09:52

Btw I am running alpha42

anmonteiro13:09:09

@dnolen thinking maybe we should also bump react to latest before beta1?

anmonteiro13:09:20

testing it locally now

anmonteiro14:09:54

@dnolen my patch to optimize recursive parsing introduced a regression

anmonteiro14:09:19

the parser will actually be there on the first invocation so I need to find another heuristic

anmonteiro14:09:25

working on a fix

samflores14:09:30

I'm pretty new to Om.Next (and Om in general) and still trying to wrap my head around some things. I think I understand most of the architecture, the reconciler, the parser and loading data from remotes. My doubt is about creating new data on the server using the UI. Is there some built-in mechanism in which the mutate function will talk to the remote just like the read function may trigger the send or I should send new data directly to the server using ajax, ws or anything else?

anmonteiro14:09:50

@samflores if you return :remote true (or whatever the name of your remote is) in a mutation, the transaction will be sent to the server

anmonteiro14:09:26

so (om/transact! [(person/create! {:name “António"})]) will result in your server getting [(person/create! {:name “António"})]

anmonteiro14:09:50

means your server parser must know how to handle the person/create! mutation

samflores14:09:07

I just tried it. Works perfectly (I should have tried it before asking picard-facepalm)

samflores14:09:38

I have another question, specially for you, @anmonteiro 😄

samflores14:09:17

I'm using compassus and I'm not sure how to define routes like /things/1 and /things/2 in a way the number could represent any thing id

anmonteiro14:09:07

@dnolen fixed in https://github.com/omcljs/om/pull/762 also submitted another one to bump React

anmonteiro14:09:26

@samflores right there has been some discussion about it

anmonteiro14:09:08

that concern was first brought by @cmcfarlen, and my response was that that’s not really a concern of Compassus

anmonteiro14:09:45

i.e. things like Bidi give you those parameters, which you can save to your app-state however you like

anmonteiro14:09:14

the actual thing that Compassus cares about is to switch your top-level component to Things

anmonteiro14:09:38

IMO it’s then the Things component’s concern to know which element it wants to show

samflores15:09:42

that's how I thought, but didn't managed to make it work last night. I'll keep that path. thank you

cmcfarlen15:09:00

@samflores What I ended up doing that works great is to call om/transact! and pass the pushy query parameters to a route/set-params mutate fn that knows how to set up the state from the url information

cmcfarlen15:09:47

Call om/transact! from the pushy handler callback that is. Just before calling compassus/set-route!

anmonteiro15:09:33

@cmcfarlen seems like a pretty good idea. However I don’t like to perform 2 transactions for what should eventually just be one

anmonteiro15:09:52

maybe we could find a way to plug that transaction into the set-route! call

anmonteiro15:09:57

feel free to open an issue to track that

cmcfarlen15:09:41

@anmonteiro: sure. I'll make a simple example to demonstrate the approach so we have something to point at and discuss

anmonteiro15:09:50

awesome, thanks!

jannis16:09:43

Mmh, I have an Om Next question. It's been a while. 😉 Is there any particular reason for the following difference? I.e., why is the key in the query result [:url _] if the link is at the top level and why is it :url if it's inside a join? (parser {} '[[:url _]]) -> {[:url _] <value>} (parser {} '[{:foo [[:url _]]}] -> {:foo {:url <value>}}

jannis16:09:07

Being aware of the second behavior, I was expecting the first query to result in just {:url <value>}.

anmonteiro16:09:24

@jannis my question would be: are you using db->tree in both cases?

jannis16:09:09

In neither case

anmonteiro16:09:29

hrm that just sounds odd

anmonteiro16:09:42

anyway, Links are only resolvable in db->tree

anmonteiro16:09:25

and using them at the top level just doesn’t make any sense

anmonteiro16:09:42

because you could just write [:url] since the property is at the top level

jannis16:09:00

I use a completely custom implement of read against DataScript, so there's no denormalization etc.

jannis16:09:41

Right, in that case [:url] would make sense.

jannis17:09:33

My situation is more complex, as I'm wrapping read in another function and the way the wrapping function calls the real read makes the parser think the link is top-level even though it isn't. A slightly crude setup, I admit. At least I now understand that that's what causes the [:url _] key in the result. 🙂

dnolen20:09:35

hrm I’m starting rethink the om/transact! requirement that the component implement IQuery

dnolen20:09:03

I believe when I made this restriction I was focused on getting the query system right, and a component that triggers a transaction without a query was distraction

dnolen20:09:42

but it seems to me we can simply discard these components during render (they don’t implement query) and we’ll find the components that actually were listening for those properties anyway

dnolen20:09:59

@anmonteiro your opinion is welcome here ^ 🙂

anmonteiro20:09:55

@dnolen I tend to agree that we could relax that requirement

anmonteiro20:09:23

but not remove it entirely, i.e.: the root component must implement IQuery

dnolen20:09:33

right of course

dnolen20:09:48

but the above would then mean that people don’t need to structure their app so strictly for no reason

anmonteiro20:09:51

the only place that would need some love after that change would be reconcile!

dnolen20:09:12

@anmonteiro yes (my point about skipping those components that don’t know what they need)

anmonteiro20:09:23

oh, just skip them entirely

dnolen20:09:29

that’s right

dnolen20:09:37

seems like a simple fix

anmonteiro20:09:41

so what’s the difference between that and transacting agains the reconciler?

anmonteiro20:09:30

@dnolen gotcha, makes sense to me, but we need to document that if people transact! against a component that doesn’t implement IQuery, they necessarily need to provide keys to re-read

anmonteiro20:09:02

because nothing will be queued by default

ethangracer20:09:09

@anmonteiro all om components have access to the reconciler, correct? wouldn’t it work the same way as just transacting against the reconciler?

anmonteiro20:09:20

the other alternative is to queue the first parent that implements IQuery

ethangracer20:09:58

it would trigger a root render every time, which isn’t ideal

anmonteiro20:09:01

@ethangracer well.. get-reconciler is supposed to be private 🙂

anmonteiro20:09:24

and I don’t see what would trigger a root render?

ethangracer20:09:00

transact could conceivably be set up to be called on the reconciler if the component doesn’t have its own query

ethangracer20:09:20

it’s definitely not the most efficient solution, but if they don’t provide follow on keys, their loss

anmonteiro20:09:25

transact! always runs against the reconciler anyway

ethangracer20:09:00

right, sorry I confused my words. without follow on reads would just trigger a root rerender

anmonteiro20:09:08

@dnolen this might be easier to implement than I thought

anmonteiro20:09:35

if it’s a reconciler or it doesnt implement IQuery

anmonteiro20:09:44

no need to mess with reconcile! in that case I think

dnolen20:09:20

@anmonteiro so are you suggesting that if not iquery? call get-reconciler and make it the same case as reconciler?

dnolen20:09:56

giving that a shot

anmonteiro20:09:50

@dnolen and as @ethangracer suggested, this will make the app always re-render from root

anmonteiro20:09:16

(because the queue will be empty)

dnolen20:09:19

only if you don’t implement IQuery

anmonteiro20:09:35

that’s what I meant, sorry

dnolen20:09:44

right I don’t have a problem with that though

anmonteiro20:09:57

me neither, it’s the same as transacting against the reconciler

anmonteiro20:09:19

it won’t actually re-render everything, we just can’t take advantage of incremental rendering there

anmonteiro20:09:28

React will still perform the diffing

dnolen20:09:33

yeah it just doesn’t seem like a huge problem to me

dnolen20:09:48

since A) everyone was discouraged from doing it, B) you can add a read to avoid

anmonteiro20:09:33

another plus side is it makes for a very small diff 🙂

anmonteiro20:09:47

good if we don’t want to introduce regressions just before beta

anmonteiro20:09:44

@dnolen just saw the commit, I still think we should check that at least the root should implement IQuery

anmonteiro20:09:04

calling it a night now, traveling early tomorrow

dnolen20:09:53

@anmonteiro hrm need to think about that - since everything is supposed to work even if you never implement IQuery (I thought we had that as a test case or something)

dnolen20:09:00

we’d just pass the state down

anmonteiro20:09:16

@dnolen but if you don’t implement IQuery you can’t call the parser

anmonteiro20:09:33

and IMO Om Next apps should work without a parser

anmonteiro20:09:39

e.g. for plain React interop

dnolen20:09:59

@anmonteiro yes it should work without the parser, but where is this going to be a problem?

anmonteiro20:09:25

well it’s not a problem if people don’t call transact!

anmonteiro20:09:42

which you probably won’t anyway, so I’m fine either way

dnolen20:09:53

@anmonteiro ah you’re just talking about some validation here

anmonteiro20:09:07

it would just serve validation purposes, basically

dnolen20:09:08

check that the reconciler has a root component that implements IQuery

anmonteiro20:09:27

maybe even an invariant would suffice

anmonteiro20:09:45

instead of a hard assert

hlolli21:09:54

I wonder why passing down a state to a component that doesn't implement IQuery can't be ok even if using transact. I know it would cause the component to lose its state. But why does it have to be like this, just open thougt as user. (there is to say give a factory a map).

dnolen21:09:00

@hlolli why does it seems like a problem?

hlolli21:09:48

Its not a problem as I know to implement IQuery. But if I render a component that reads a global state, but after rerender I wouldn't want to re-read that state, but still keep it like it was at mounting time. I know ways around this. But it would be nice (if that comes at no cost) to just say from root component (render [this] (factored-component {:a "state" :that "stays"])

dnolen21:09:27

@hlolli sorry re-reading your statement, I think we are in agreement

dnolen21:09:34

cut 1.0.0-alpha43 to make sure this change doesn’t cause any issues

hlolli21:09:41

cool, of course the temptation would be to add reads on every key the component uses, and most of the time I do that. But I would only assume, that when appropriate, not to re-read, would hopefully increase performance.

hlolli21:09:13

ok cool, no more from me, would be great update!