Clojurians
# om

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

grzm 19:31:39

I'm debugging what looks like a server-side transit encoding issue. While debugging, I want to create an edn literal that includes an #om/id tagged literal. Here's what I'm trying:
(def edn-body {some/new-item {:tempids {#om/id["2e486bfc-aacb-4736-8aa2-155411274e84"] 852154481843896390}}}) When I do so, I'm getting No reader function for tag om/id Is there a way to quote this so the compiler ignores it? Or include a reader?

peeja 20:07:57

It looks like componentWillReceiveProps receives a next-props that doesn't include children. Is that right? And if so, what's the correct way to get the incoming children?

chris-andrews 20:14:34

@grzm You might want to check in the #clojurescript channel for more info about readers. I don’t think you can quote literals; they need to be defined

chris-andrews 20:15:04

@peeja what are you trying to do with the incoming children in componentWillReceiveProps?

peeja 20:15:32

Store them in state to delay their appearance

chris-andrews 20:16:08

these are the child components, not props?

chris-andrews 20:16:27

(not too familiar with the what children are in om)

peeja 20:16:48

In React, children is just another prop

peeja 20:17:10

It's specified in a special way when you create the element, but it comes in as this.props.children

peeja 20:17:44

But Om appears to pull it out, and then doesn't give you a way to access it before it's available as (om/children this)

chris-andrews 20:19:19

Not sure how much this helps, but I think componentWillReceiveProps behaves a bit differently in om.next than react

peeja 20:20:02

So, is there a way to get the incoming children?

peeja 20:20:52

I thought one of the great things about om.next was that you had access to the real React lifecycle

chris-andrews 20:20:58

You can access them, but you might not be able to rely on setting state in response to the incoming children like you’re after

chris-andrews 20:21:53

There are other people here who probably know this better than me, but my understanding in the past at least was that the lifecycle is slightly different because om.next renders asynchronously and batches changes

peeja 20:22:20

Oh, wow, it does? It takes over the render cycle?

chris-andrews 20:22:57

I think it does to some degree, and I think that means that setting state in your lifecycle isn’t quite the same as how it works in react

chris-andrews 20:23:16

I believe there was talk about removing componentWillReceiveProps at one point for this reason

peeja 20:23:41

Yikes. Okay…is there a better way to write a React-like component?

chris-andrews 20:23:52

because it basically exists in react so that you can set state and guarantee that your state will be updated properly in time for the rest of the lifecycle

peeja 20:24:14

This isn't an iquery?, it's a dumb component which handles some visuals

peeja 20:24:40

I thought the correct way to handle that was to use defui and only implement the lifecycle methods

peeja 20:24:47

but maybe even that's inappropriate

chris-andrews 20:25:33

You can rely on the lifecycle methods being called in the right order and everything, but the local state in om is just a bit different

chris-andrews 20:26:04

My workaround was just to put an atom in local state and swap! the value in the lifecycle

peeja 20:26:22

Oh, I'm not too concerned about that, then, I think. I'm actually going to be pushing it into a core.async channel

peeja 20:26:58

Well, that's not entirely accurate. When it comes out of the channel, the element will have to go into the state to be rendered

chris-andrews 20:28:09

So the impression I got was that when you call the om functions to update state, they are really queuing that state update, and it seemed like you might not be able to count on state and props updating in lock-step like with react

chris-andrews 20:30:02

I think you should be able to accomplish what you need by using the lifecycle but just staying away from om/set-state or whatever the exact fn name was

peeja 20:31:26

That actually shouldn't be a problem for me: I need a props update (new children) to give me a chance to put the new child in a channel, and when I pull it off the channel I need to put the child in the state and cause it to render. Getting state and props to update in lockstep doesn't matter to me.

peeja 20:31:40

I just need to access the children from the props at all

peeja 20:31:53

Maybe I should be using componentWillUpdate instead?

chris-andrews 20:32:16

yeah, basically the other lifecycle methods ended up being my go-to

anmonteiro 20:33:16

@peeja: Om Next renders incrementally in some cases, which means that componentWillReceiveProps will not be called in those cases

anmonteiro 20:33:56

There's a patch to address this that is waiting to be merged

anmonteiro 20:34:37

To be clear, componentWillReceiveProps is currently only called when rendering from the root

chris-andrews 20:35:07

oh, thanks for clarifying that

anmonteiro 20:35:14

So I would first check if it is being called at all

anmonteiro 20:35:31

Only then try to get at the children

peeja 20:35:58

Well, it is, but I'm not using an Om Next reconciler ATM

peeja 20:36:11

This component is in an om.core app, for now

peeja 20:37:46

What does rendering incrementally mean in Om Next? I saw some mention of that, but I assumed it was about compatibility with React Fiber.

anmonteiro 20:39:01

Rendering incrementally means that only the subtree rooted at the transacting component will be re-rendered

anmonteiro 20:39:54

Along with any other places in the app that query the same data

peeja 20:40:07

In which case the transacting component wouldn't get componentWillReceiveProps, but its children would, right?

anmonteiro 20:40:22

Queries + the indexer give us the knowledge to do this

anmonteiro 20:40:32

@peeja: yes that's right

peeja 20:40:45

That's fine, then; this component isn't iquery?

anmonteiro 20:41:26

My proposed patch addresses just that: https://github.com/omcljs/om/pull/743

peeja 20:41:52

Ah, neat

anmonteiro 20:42:03

@peeja: right so if you're not using an Om Next reconciler you shouldn't be worried about these problems

anmonteiro 20:42:38

Because even though you have an Om Next component you're using om.core's rendering loop

peeja 20:43:38

Right, all I'm looking for is a way to be notified when my component's children change

peeja 20:43:54

just as I can see when other props change

peeja 20:44:47

React gives you nextProps.children, but there's nothing in Om's next-props

anmonteiro 20:45:13

I don't think there's an obvious way to do that

peeja 20:45:22

Is that intentional?

anmonteiro 20:45:29

Probably not

peeja 20:45:34

:thumbsup:

anmonteiro 20:46:45

@peeja: you might want to open an issue to track that, but I'm not entirely sure how to solve that one in a clean way

anmonteiro 20:47:30

Probably have the children be a computed property in next-props, not sure

anmonteiro 20:48:09

I'm also not in front of a computer so can't really look at that right now

peeja 20:49:38

That would make sense to me.

calvis 21:01:05

is there a tempid guide/documentation somewhere? it’s not “Just Working” and I have no idea how to debug

anmonteiro 21:08:22

@calvis: I think as a starting point this one is somewhat insightful: https://github.com/awkay/om-tutorial/blob/master/src/cards/om_tutorial/om_specs.cljs#L14

grzm 21:08:44

@chris-andrews: It's actually on the server side. I ended up using the tempid constructor rather than the reader literal.

anmonteiro 21:10:38

@calvis: that one is really just an example to prove it works I've got a complete working example with a Datomic backend here:
https://github.com/anmonteiro/talks/tree/master/2016-berlin-meetup

calvis 21:11:25

@anmonteiro: thanks I like how minimal that is — is :id-key required? what if I had tempids for multiple idents coming back

anmonteiro 21:12:06

id-key is required and is normally the thing by which all your entities are identified

anmonteiro 21:12:26

Usually :db/id

calvis 21:12:39

I’m not using a datomic backend so :db/id doesn’t make sense

anmonteiro 21:12:44

I don't think there's a way around that

anmonteiro 21:14:04

@calvis: probably worth having the same key for all your IQuery components so that tempid migration can work

anmonteiro 21:14:15

Actually there's probably a way around that

calvis 21:14:26

yeah, I don’t have that issue atm (just one ident) just kind of wondering about the restrictions

anmonteiro 21:14:44

You'd need to override :migrate in the reconciler

calvis 21:15:07

yeah that wouldn’t be so bad

calvis 21:15:24

just break apart the tempids and call the default migrate with different id-keys

calvis 21:16:48

that doesn’t seem to help though. I’m still seeing only my old ids

anmonteiro 21:17:24

@calvis: is your state normalized?

calvis 21:17:46

yeah it is in the reconciler

calvis 21:19:09

so I copied om/default-migrate into my repl and checked the intermediate values, the call to db->tree returns a denormalized state with only the old tempids even though the pure’ expression has the new ones

grzm 21:20:37

anyone know of a command line tool to pass edn to an Om server api?

grzm 21:20:54

I'd like to test my API without needing to use a browser

anmonteiro 21:21:23

@calvis: a number of things could be going wrong, happy to look at a minimal case though

calvis 21:21:35

yeah I’ll put one together

calvis 21:52:28

@anmonteiro: in case you’re curious, I was using two different keywords for the :keyfn and the first value of the ident vector, making them the same fixed the issue. is that bad style?

calvis 21:53:51

or maybe my :id-key in the reconciler should have matched the :keyfn and it would have been fine

anmonteiro 22:00:49

@calvis: :keyfn in factory should have nothing to do with it?

calvis 22:26:43

@anmonteiro: I’m probably conflating things that don’t need to be conflated, I made an example: https://gist.github.com/calvis/31d895a924b888e8fff0e89d1cd7d8aa (essentially I picked the wrong :id-key)