Fork me on GitHub
#om
<
2017-01-13
>
raspasov06:01:38

hey all I’ve had some pretty long-term musings about React/om-next if anyone has 3 min to chat I’d love to get some feedback 🙂

raspasov06:01:40

I’ve been using React+om for like 2+ years now and somehow I still haven’t figured out 1 thing and I’m just wondering if I’m missing something super obvious

raspasov06:01:48

it boils down to this: is a parent component “required” to pass all the props to a child component that the child component needs?

raspasov06:01:37

from I understand: no, it does not BUT… it always seems to create one subtle problem for me - the fact that on the first render, the prop that isn’t passed from the parent down to the child is nil (basically not there)

raspasov06:01:05

so I’m just wondering if this is just not recommended, or I’m missing something obvious

sova-soars-the-sora06:01:14

Right! There's a caveat in using a javascript object mounted on an html page and that is ... your component structure has to look like nested DOM elements... much like html... So the "root" component effectively holds all the other components.

raspasov06:01:20

this is not a critical problem in some cases, or even most of the time, but sometimes it creates subtle animation/user experience issues

raspasov06:01:04

@sova right… continue...

sova-soars-the-sora06:01:36

The way Om.next works, there's a reconciler that keeps track of stuff, but the way it keeps track of stuff is basically by asking the root of the tree "hey yo what all do you want to keep track of while the app is running?"

raspasov06:01:21

right, yes, I’ve been using Om.next for almost a year now (I’m using it via React Native, but it’s all pretty much the same)

raspasov06:01:36

I used om-now on the web for 1+ years

raspasov06:01:40

before that

sova-soars-the-sora06:01:30

Cool. Yeah so that's what I'm confident about so far. I'm pretty new in comparison. You were wondering about why they are nil if you don't ask for them at the root element?

raspasov06:01:45

@sova they are only nil on the first render

raspasov06:01:29

on 2nd render (I think) they get populated with the proper data

raspasov06:01:49

in that chain of thought I was wondering if using om-next Idents

raspasov06:01:01

would help with that (Idents are something I haven’t used yet)

sova-soars-the-sora06:01:28

Have you tried including all the elements you query about ... from the root element "downward" to the asking component?

raspasov06:01:30

if you do pass them down all the way, they get rendered immediately

raspasov06:01:35

on 1st render, yes

sova-soars-the-sora06:01:48

It's cool you notice that. I wonder if it makes your UI code look a lot cleaner just having them in the spots you want and not all-the-way-down

raspasov06:01:59

YES! 🙂 that’s the idea

raspasov06:01:10

and the bigger “problem” is that

sova-soars-the-sora06:01:37

Because it seems like a pre-render step could be in order, to just go through the whole potential component Ui and just make its own tree that is more-or-less invisible to the coder...

raspasov06:01:37

then you effectively have to structure your data around how the UI render tree is built

raspasov06:01:57

and that is not always the cleanest data representation

sova-soars-the-sora06:01:28

Right . Hrm . Well that is a nice thing to have for verifiability of rendering and stuff... yes I see what you mean about readability.

raspasov06:01:56

one way to alleviate this issue is

raspasov06:01:06

simply make your UI tree shallower

raspasov06:01:22

and pass all the way down

raspasov06:01:41

still tedious, but at least you don’t have to pass 10 levels down 🙂

sova-soars-the-sora06:01:42

Ah, like have fewer (but more deeply HTML-nested) components... yes..

raspasov06:01:13

more like less deeply nested, same amount probably

sova-soars-the-sora06:01:05

I think for most applications a shallow UI tree is what one aims for. Or at least balance (and if possible elegance) in the breakdown

raspasov06:01:31

ok thanks for your feedback 🙂 ttyl!

sova-soars-the-sora06:01:30

yeah man. i like where you're going with that. there's probably a way to pre-render all that ... and then just not worry about making your data tree grow along your UI tree .. ttyl

azzikid09:01:18

hey everyone, i made some progress on the issue i had yesterday regarding chaining remote queries so that the result of the first query can be used as the parameter to the next query. as @hlolli recommended, i used componentWillUpdate to catch the results of the first query, and then used set-query! to update the params for the next query. it fetches the proper data! however, since i am calling set-query! in componentWillUpdate, i believe set-state is called in react, which leads to an infinite loop because componentWillUpdate keeps getting called. anyone know a way around this?

azzikid09:01:12

i also tried to use componentWillReceiveProps but that causes an infinite loop too because props are being passed in after each query.

hlolli09:01:49

@azzikid yes you need to watch out for the logic, componentWillUpdate gets called many many times. So you need to set the query only on conditions that statisfy what you need. To help you with that you have last-props and last-state that you can compare to the next state/props. So if you are seeing changes in 1 value from 1 update to next, then start the query.

hlolli09:01:31

also try componentDidUpdate, it gets only called once while componentWillUpdate gets called twice, at least as far as I see.

danielstockton12:01:47

I have some components whose queries depend on attributes of the logged in user. I'm passing user to them as a computed property and trying to access user in IQueryParams to initialize the query parameters. IQueryParams is called several times, the first few times with user: nil. I'm not sure if this is a valid pattern, or what I should be doing instead?

danielstockton12:01:27

It seems to work, except on the first load, because I initialize the properties with user: nil and they're incorrect.

danielstockton12:01:24

It's strange because componentDidUpdate gets called with the correct params and I update the url with the correct params....but it doesn't seem to be re-rendering wth them

danielstockton12:01:03

Basically, it seems like the query is sent when IQueryParams is first called (with user nil) but by the time I receive the new props, it has been called again and params have been updated correctly

azzikid15:01:57

@hlolli thanks for putting me on the right track!

azzikid15:01:48

i am trying to use set-query! on a component that is not "this" component but am getting the error: Uncaught error: Assert failed: (or (reconciler? x) (component? x))

azzikid15:01:15

when i do: (om/set-query! Sections {:params new-params})

tmulvaney15:01:29

I think you have to call it on an instance

tmulvaney15:01:47

so on the thing returned by (om/factory Sections)

azzikid15:01:07

@tmulvaney i actually tried that and got the same error 😞

hlolli15:01:48

an instance is either this or reconciler. A trick worth noting is that you can pass down this as properties of a child. It has some caveats to is.

mavbozo16:01:15

@azzikid I have tried creating the component first then set the query, ex:

(let [sc (section {})] (om/set-query! sc [:a :b]))

mavbozo16:01:25

might not be a good idea. I still try to understand om.next

azzikid16:01:43

interesting idea. i'll play around with it.

azzikid17:01:22

(defui View
 static om/IQueryParams
 (params [this]
    {:activeq {:startkey "active-data"
               :endkey "active-data"
               :include_docs true}
     :sectionsq {}})
 static om/IQuery
 (query [this]
  [:app/learn 
    '({:learn/active [*]} ?activeq)
    '({:learn/sections [*]} ?sectionsq)])

azzikid17:01:19

any reason why that query would only call the read method for :learn/active but not for :learn/sections? they are both remote if that matters.

azzikid17:01:51

i want all three queries (:app/learn, :learn/active, :learn/sections) called. they are all top-level in my state.

mavbozo18:01:32

@azzikid your query definition is wrong in specifying parameter => '({:learn/active [*]} {:activeq ?activeq})

sova-soars-the-sora19:01:37

@danielstockton I was just talking with @raspasov about this very issue. It will eventually render but the first pass through is nil, presumably because whatever query you want to do doesn't do the walk all the way from the root component to the asking component (meaning one would need that query piece in the root component and every component that nests around your asking component). Not having it there will still render the data, but it is nil on the first pass-thru ... is my understanding thusfar

tmorten23:01:00

I have an interesting issue: when I use set-query! to set a parameter inside of componentWillUpdate (based upon the next-state), it triggers a parser read and hits remote if necessary. When remote is hit, parser is re-read again and merged into app-state, however, this time the parameter is missing from the query...anyone else have this issue?