Fork me on GitHub
#om
<
2016-09-17
>
peeja16:09:03

If I query for a prop in a component, key->components with that prop finds the component. If I query for an ident in a component, key->components with that indent doesn't find the component. In both cases, the key that's queried for ends up in the indexer in :prop->classes, but the indexer only looks there for keywords: https://github.com/omcljs/om/blob/master/src/main/om/next.cljc#L1901

peeja16:09:01

key->components for an ident appears to only find components whose ident is that ident, not components which query for the ident

peeja16:09:08

Is that a bug, or am I missing something?

peeja16:09:53

In my case, I have a parent querying with the ident, rendering a child whose ident is that ident. At first, there's no data, so the child has no props, so it can't calculate its ident properly. When the remote data comes in, I need the parent to re-read so that it gives the child its props. The child doesn't know to re-read because it doesn't have an ident until there's data back from the server.

peeja16:09:39

I suppose the parent could cheat its knowledge of the ident into the child's params somehow, but that feels like it's not the way it's supposed to work.

peeja17:09:02

(Also, if the parent queries by an ident and shows the data from that ident directly, rather than using a child component, the parent won't be updated when new data comes in.)

anmonteiro17:09:40

@peeja sorry that’s doesn’t make a lot of sense

anmonteiro17:09:03

I think we index idents as idents and links as props

anmonteiro17:09:14

unless you’re conflating the two

peeja17:09:27

Ah, I didn't realize there was a clear line between the two

peeja17:09:31

Which is which?

anmonteiro17:09:15

ident: [:x/by-id 1]; link: [:x ‘_]

anmonteiro17:09:26

the difference is the _

peeja17:09:48

Oh, really? I thought they were both idents and links…

peeja17:09:01

The documentation calls them both both, AFAICT

peeja17:09:33

> Om Next is designed out of the box to fix this problem by making links (also called idents) a first class concept.

anmonteiro17:09:12

so they’re both idents. but links are called “unique idents"

anmonteiro17:09:44

the difference is in the semantics

peeja17:09:09

Got it. That makes sense. The tutorial's a bit ambiguous, but it's pretty old at this point.

anmonteiro17:09:42

an ident (not link) refers to something in the (normalized) app state that you can access with get-in (e.g. (get-in app-state [:x/by-id 0]))

anmonteiro17:09:48

a link doesn’t have that property

peeja17:09:54

In this case, I'm talking about a regular ident

anmonteiro17:09:16

so regular idents are not indexed by their key

anmonteiro17:09:32

they’re indexed as themselves

peeja17:09:49

Right, but only the components which have the ident as their ident are indexed

peeja17:09:58

Not the components which read the ident

anmonteiro17:09:40

pretty sure they are?

anmonteiro17:09:50

look at the tests I linked above

peeja17:09:11

If I have a component whose query is [{:current-user [:user/name]} {[user/by-id 5] [:user/name]}], that component is indexed by :current-user, but not by [user/by-id 5]

peeja17:09:46

Huh. That does say what you're saying

anmonteiro17:09:13

it’s hard for me to believe what you’re saying because the tests pass 😛

peeja17:09:20

That's fair 🙂

peeja17:09:44

But that's good news for me. That means my app is doing something wonky, but my expectations of Om are correct

anmonteiro17:09:13

@peeja so here’s something that happened to me and could be happening to you

anmonteiro17:09:25

you have component with ident [:x/by-id 0] mounted

anmonteiro17:09:51

your remote returns a response with [:x/by-id 2], but that’s not indexed because it never mounted

anmonteiro17:09:15

it won’t re-render [:x/by-id 2 ] or associated components

peeja17:09:04

I'm not sure I follow. What would you want to re-render, if there's no [:x/by-id 2] mounted?

anmonteiro17:09:25

wait that’s not the correct explanation

anmonteiro17:09:20

right, so the real problem is: you have a component with ident [:x/by-id 0]. now your route changes and you want to show entity with ident [:x/by-id 2]

anmonteiro17:09:48

this might get funky because React reuses instances

anmonteiro17:09:02

so although you’re rendering [:x/by-id 2] now, the component’s ident didn’t change

anmonteiro17:09:15

@peeja that make sense? ^

peeja17:09:46

Oh, yeah, I think so

anmonteiro17:09:05

then although [:x/by-id 2] is mounted, it’ll never re-render because the component’s ident is [:x/by-id 0]

anmonteiro17:09:25

so the solution is to make the component’s ident depend on the current route

peeja17:09:26

But won't it re-render because the parent will pass it new params?

peeja17:09:44

if the parent's query depends on the route

anmonteiro17:09:21

it won’t re-render in the following case: 1. you make a remote call with query [{[:x/by-id 2] [:foo :bar]}]

anmonteiro17:09:57

2. [:x/by-id 2] is queued for re-render in merge!

anmonteiro17:09:26

but the component’s ident is [:x/by-id 0] because React reused the instance 🙂

anmonteiro17:09:50

OK that was hard to explain but I think it’s clear now?

peeja17:09:09

By the time 1. happens, why hasn't the ident already become [:x/by-id 2]?

anmonteiro17:09:01

in my case, because the parser assembled the query’s ident based on the current route

anmonteiro17:09:12

but the component’s ident didn’t depend on that route

anmonteiro17:09:04

that said, this was a few months ago so I don’t know if I would structure that app the same way

peeja17:09:16

and if the ident is based on the component's data, the data coming in from the server, it doesn't update the ident until it re-renders, but it doesn't re-render because it hasn't updated to the new ident

peeja17:09:27

Is that the trick?

peeja17:09:36

It's a chicken-and-egg problem

peeja17:09:49

So, that's not exactly what I'm hitting, but it's pretty close

anmonteiro17:09:58

might be a variation

peeja17:09:20

This is when the app is first loading, and I mount the child, but with empty params, because there's no data loaded yet

peeja17:09:32

so its ident is [:x/by-id nil]

peeja17:09:16

But it seems like when the data comes in the parent should be re-rendering, and that that should set everything right again

anmonteiro17:09:55

so it seems to me that’s exactly the same problem

peeja17:09:57

For some reason, the indexer doesn't find the parent, but it seems like if that were working, the whole thing should work again

peeja17:09:20

(Yeah, you're right, it is the same problem after all)

anmonteiro17:09:53

here’s something for you to try: in your parser, return {:keys [...]}

anmonteiro17:09:14

and override :merge in the reconciler so that it also queues the keys that you return from the parser

anmonteiro17:09:34

I’m not certain that will work, but it would be an elegant solution 😛

peeja17:09:43

Huh, that's a neat idea

peeja17:09:53

Oh, but that doesn't solve the problem here

peeja17:09:02

merge is returning the right keys

peeja17:09:14

The key doesn't point to the parent component

peeja17:09:29

(but it should, according to those tests)

peeja17:09:54

@anmonteiro Oh! I misread the test.

peeja17:09:12

That only tests that the ident shows up in :prop->classes!

peeja17:09:29

It shows up in my :prop->classes too, but the indexer doesn't look there for idents

peeja17:09:55

It has to be a keyword for the indexer to look there: https://github.com/omcljs/om/blob/master/src/main/om/next.cljc#L1901

anmonteiro17:09:14

seems like a bug maybe?

peeja17:09:20

Seems like it to me

peeja17:09:28

Otherwise there's not much point storing it there 🙂

anmonteiro17:09:52

@peeja awesome, thanks for digging in. open an issue and I’ll get to it

mjhamrick17:09:01

If anybody wants to poke around, I made a clone of codenames (a fun little board game) using om-next. Code is here https://github.com/diminishedprime/secret-agent-ui suggestions are welcome.

anmonteiro17:09:38

@peeja btw currently working on cool stuff for Compassus, should solve this one in a nice way: https://github.com/compassus/compassus/issues/3

peeja17:09:43

@anmonteiro I notice the indexer has this extfs that's overridable. Is that something I could use to implement a workaround for now?

anmonteiro17:09:22

should also allow for setting params, not only queries

peeja17:09:38

Ah, you can pass in :indexer. Perfect!

anmonteiro17:09:21

no idea how to play though 🙂

mjhamrick17:09:05

@anmonteiro , take a look at this pdf if you're interested. http://czechgames.com/files/rules/codenames-rules-en.pdf Needs at least 2 players, much better with 4 or more (in my opinion)

mjhamrick17:09:21

I found out about the game at clojure-conj last year.