This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-12
Channels
- # admin-announcements (3)
- # beginners (13)
- # boot (52)
- # cbus (1)
- # cider (13)
- # cljs-dev (70)
- # cljsjs (16)
- # cljsrn (124)
- # clojure (129)
- # clojure-austin (3)
- # clojure-boston (2)
- # clojure-russia (238)
- # clojure-sg (3)
- # clojurescript (119)
- # cursive (18)
- # datomic (22)
- # editors-rus (2)
- # events (1)
- # hoplon (160)
- # jobs (1)
- # jobs-rus (8)
- # ldnclj (31)
- # ldnproclodo (1)
- # lein-figwheel (4)
- # leiningen (8)
- # off-topic (3)
- # om (335)
- # onyx (29)
- # re-frame (15)
- # reagent (12)
- # robots (1)
- # yada (19)
hmm, how to trigger renders when remotes return and the data is merged with the app state?
yeah it seems like I should put reads somewhere but I’m unclear on where they should go
yeah, my root component wants the key :remote/msg
and the read for that returns a remote ast which causes send to get data from the server which is correctly merged into the app state but no re-render
I’ve tried with and without, if I supply one then my root component gets the initial value but not the new one when the state is merged from the remote. If I don’t supply one then it just never is rendered with that prop
I had been trying with just a hard coded value and it was always getting that. Stupid on my part.
this is the read code I’m using now which works great: https://www.refheap.com/111605
If I am building an app with several distinct pages, does it make sense to use set-query!
on the root component to swap the query out with a new page’s “root query” when the user switches pages?
Alternatively I think you could put the reference to a component for that page somewhere and use get-query
on that.
Like current-component
is DetailComponent
which has subcomponents. Your root is just querying current-component
. On a new page, you swap that with a different component
Putting a presentation on om next together right now.
One thing I noticed about relay is that you can defer elements that are not important, like if you want to have comments
in your app but it's not critical, you defer it and it loads in whenever it is ready. Can I do something similar in next?
It seems like the components will render when data is there. I'd like to give them a default value like :not-loaded-yet
, which I could use to display loading indicators where necessary
(defmethod read :foo/bar
[{:keys [state] :as env} key params]
(if (find @state key)
{:value (get-data state key)}
{:remote true :value :not-loaded-yet}))
sadly doesn't work 😛@dvcrn Looks ok to me except I'd deref the state once only. It might change between find and get-data. (I really don't know anything about concurrency in JS...) What doesn't work exactly?
@dvcrn: Partial loading is something I've been interested in as well. So far no delay-like capability. Your primary option is to filter your queries based on your current state, or use query params to change their behavior. Both involve embedding extra logic in your reads to figure out if it should be elided.
I get ReactDOM is not defined if I use Sablono and take out om.dom in the om.next quick-start. Is that expected? I’m using om 1.0.0-alpha19 Here’s the “broken” version...
(ns om-tutorial.core
(:require
[goog.dom :as gdom]
[om.next :as om :refer-macros [defui]]
;;[om.dom :as dom]
[sablono.core :as html :refer-macros [html]]))
(defui Counter
Object
(render [this]
(html [:div "Howdy"])))
(def counter (om/factory Counter))
(js/ReactDOM.render
(counter)
(gdom/getElement "app”))
You can workaround it by by requiring cljsjs.react.dom in one of your own namespaces.
@dnolen: … I’m using boot in place of lein, just for the heck of it. Not surprisingly, it works too. All good stuff.
@jannis can i ask how you wired up the server-side bits of tempids? i tried passing om.next.server/reader
to my middleware and then saw you’d already attempted that with no luck.
After that, you have to return a :tempids
map from mutations that create real IDs. I'm simply reusing the id
part of tempids for the real IDs at the moment: https://github.com/Jannis/copaste/blob/master/src/server/parsing/copaste.clj#L78
i’ll take a look, thanks!
@joshfrench: Any questions, just ask
@boz: In my build.boot I have react and react-dom "0.14.0-1" in my deps and then: [sablono "0.4.0" :exclusions [cljsjs/react] [org.omcljs/om "1.0.0-alpha20" :exclusions [cljsjs/react cljsjs/react-dom]]
hmm, is tree->db
intended remove values that are not included in the given components query?
@thosmos: like this?
(set-env!
:source-paths #{"src"}
:resource-paths #{"resources"}
:dependencies '[[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.170"]
[adzerk/boot-cljs "1.7.48-6" :scope "test"]
[adzerk/boot-cljs-repl "0.2.0"]
[adzerk/boot-reload "0.4.1"]
[pandeiro/boot-http "0.6.3" :scope "test"]
[cljsjs/react "0.14.0-0"]
[cljsjs/react-dom "0.14.0-0"]
[org.omcljs/om "1.0.0-alpha20" :exclusions [cljsjs/react cljsjs/react-dom]]
[sablono "0.4.0" :exclusions [cljsjs/react]]])
I don’t think sablono has a cljsjs/react dependency. At least it’s not listed on http://clojars.org or in my deps graph (before making the above change.
I still get the same behavior. e.g., have to require cljsjs.react.dom in my cljs namespace.
Oops, I just took a closer look at your example, you're calling js/ReactDOM directly, so yes you'd need to require cljsjs.react.dom
It happens with om.next’s add-root! too, which defaults to using ReactDOM … it’s documented. I just didn’t get it.
@noonian: yes, we could change that but would like to hear more rationale about why you have stuff not in queries
@noonian: in any serious application with a remote component that wouldn’t even be possible
@boz: I think for Om to work with React Native, you have to use something else instead of ReactDOM.render
.
I'm attempting to use a normalized datascript db where entity refs use the :db/id , like so: {:db/id -6 :type :dashboard/list :list/title "A List of Various Media" :list/items [-1 -2 -3 -4 -5]}
is it possible to make this work with om/Ident without creating a separate items-by-id index?
@dnolen: I’m curious why it woudn’t work for remote. But my issue fundamentally has to do with normalization. I have a parser with recursive reads (which are reflected in the query as keys that do not show up in the data I want to normalize). That means that tree->db with the root component doesn’t really work to normalize the data. It does work to normalize with the sub query fragment that is inside the recursive key. So I’m manually normalizing my data using that approach currently but if the outer component wants any keys tree->db will strip them from the data unless I “whitelist” the keys by adding them to the sub query which is dirty. It seems to me that you will run into this issue anytime you have components that leverage recursive parsers. It also seems like any sort of routing example requires a recursive parser.
If I try to set the Ident to just a plain id I get an error: (defui Post static om/Ident (ident [this {:keys [id]}] id) ... error: Uncaught TypeError: Cannot read property 'om$isComponent' of null
Does this approach of manually normalizing the data when using a recursive parser make sense? It also leads to questions about how to merge in new data from remotes. Currently I think I’d have to keep Om not auto-normalizing and override merge functions to do my custom normalization because Om hardcodes calls to tree->db
on the root component. But if one could instead configure the reconciler with a function to get the query to normalize with it would allow someone with a recursive parser to take advantage of auto-normalization without implementing custom merge functions etc.
however I don’t really understand why you want to do that since it automates a lot of work for you
This works. I was mixing up how datascript handles references in queries with how Om knows an entity's id. (defui Post static om/Ident (ident [this {:keys [id]}] [:db/id id])
@dnolen: I think I need to post some queries to make this explicit and also my goals as far as the structure of app-state.
@dnolen: ok here is a minimal example of what I’m talking about that builds on the “Components, Identity & Normalization” tutorial: https://www.refheap.com/111633 Left out is the motivation for the recursive read but its basically the same reason as in https://github.com/jdubie/om-next-router-example/blob/master/src/om_router/core.cljs
@noonian: that’s just a lot of code with no explanation of what I should be looking at
I am currently trying the Quickstart and I get the following error with the part where I start fighweel for the first time:
Analyzing src/om_tutorial/core.cljs
Analyzing jar:file:/Users/mitkuijp/.m2/repository/org/omcljs/om/1.0.0-alpha20/om-1.0.0-alpha20.jar!/om/dom.cljs
Exception in thread "main" clojure.lang.ExceptionInfo: No such namespace: cljsjs.react, could not locate cljsjs/react.cljs, cljsjs/react.cljc, or Closure namespace "cljsjs.react" {:tag :cljs/analysis-error}, compiling:(/Users/mitkuijp/Development/om-tutorial/script/figwheel.clj:17:1)
Anyone recognize this?@dnolen: hehe ok sorry. The People component is the RootView component from the tutorial. All I do is nest that under the :page/content
key which in the read implementation just parses the query from the root.
and the automation you were talking about hardcodes that tree->db is called with the root component
so in short I’d love to use that automation but either I need to find a different approach or configure what query om will use for normalization
because the structure of init-data does not match the shape of the root query (due to the recursive parse key)
that is sort of why you would want to nest something that queries keys at the root under a parent component
but its more the mismatch between the shape of the app state and the shape of the query
which I believe will happen anytime you have a UI tree that uses keys that trigger recursive parses
ok, this is the query in question that I would like to be able to normalize data with: [{:page/content [{:list/one [:name :points]} {:list/two [:name :points]}]}]
are you saying that I can’t maintain app state of the shape:
{:list/one
[[:person/by-name "John"]
[:person/by-name "Mary"]
[:person/by-name "Bob"]],
:list/two
[[:person/by-name "Mary"]
[:person/by-name "Gwen"]
[:person/by-name "Jeff"]],
:person/by-name
{"John" {:name "John", :points 0},
"Mary" {:name "Mary", :points 0},
"Bob" {:name "Bob", :points 0},
"Gwen" {:name "Gwen", :points 0},
"Jeff" {:name "Jeff", :points 0}},
:om.next/tables #{:person/by-name}}
with that query?right, I understand that, but the query I want to use for normalization isn’t the root query. I think you are saying that isn’t something you want to do with Om but I am trying to understand why not now.
so wouldn’t it be something like this?:
(def init-data
{:page/content
{:list/one [{:name "John" :points 0}
{:name "Mary" :points 0}
{:name "Bob" :points 0}]
:list/two [{:name "Mary" :points 0 :age 27}
{:name "Gwen" :points 0}
{:name "Jeff" :points 0}]}})
that makes sense to me, but throws an error in tree->db I believe because one of the components in the tree doesn’t have an ident
ok, but even then I would expect to be able to normalize this data with the root query above:
{:page/content
[{:list/one [{:name "John" :points 0}
{:name "Mary" :points 0}
{:name "Bob" :points 0}]
:list/two [{:name "Mary" :points 0 :age 27}
{:name "Gwen" :points 0}
{:name "Jeff" :points 0}]}]}
is that a correct expectation? if so I think theres a bug in Om, if not then Im misunderstanding something.
and the query: [{:page/content [{:list/one [:name :points]} {:list/two [:name :points]}]}]
Hmm I got the quickstart working with the following project.clj
(defproject om-tutorial "0.1.0-SNAPSHOT"
:description "My first Om program!"
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.145"]
[org.omcljs/om "1.0.0-alpha20"]
[com.cognitect/transit-clj "0.8.281" :scope "provided"]
[com.cognitect/transit-cljs "0.8.225" :scope "provided"]
[figwheel-sidecar "0.5.0-SNAPSHOT" :scope "provided"]])
@noonian: and actually that issue doesn’t make sense we can’t normalize singletons since we don’t know which one to pick
and all data for each page should go in pages and use references to point to tables of denormalized data if it represents the same data right?
yeah I’m double checking things over here to make sure there isn’t a bug for this case
np, its what I’ve been trying to get working since I jumped into Om next but was suprised no one else seemed to run into this
@noonian: people have like @thomasdeutsch
yeah, I was definitely pushed that way but I think I hit bugs that I thought were om next semantics hehe
@dnolen: I had the same problems as @mitchelkuijpers trying to run through the Quick Start last night and I can confirm that adding the transit deps and using figwheel-sidecar “0.5.0-SNAPSHOT”
fixes the issue
@kschrader: ah right … will fix
Awesome quickstart btw @dnolen Finally time to play with om.next
@mitchelkuijpers: thanks!
@dnolen: ok I’m still having trouble normalizing with a union. I have a much smaller example now but the tables created by tree->db have nils instead of the ids from props. Either a bug still or my data/query syntax is off. Here’s the example: https://www.refheap.com/111640
ident is called twice for the page during normalization and with print debugging it seems it only gets the correct props the first time called
yeah, I based it off the union tutorial and tried to make sure the shape of everything was the same
so PageView corresponds to DashboardItem and RootView to Dashboard and PeoplePage to Post, Photo, or Graphic
I think the issue is in the union. In the tutorial you are unioning on the type of the dashboard item. How does Om know to compute the union from the type key?
@jannis also I don’t know about OM-470 anymore https://github.com/omcljs/om/issues/470
@dnolen: ah I got it working. I must have git pulled too soon and still had the buggy version. Re-pulling and installing alpha22-SNAPSHOT fixed it
1) if the component listens to it, you want to pass in the query the component uses for that key, not just the key itself, otherwise query
in read
will be empty on the remote end and you'll get nothing useful back
if a user drops a key, find all the components that listen on that key and get their queries for that key
2) if other components listen for the same key... I don't know... would we collect and re-execute all queries for keys passed to transact!
and send them all over?
It's kinda what my hack does except doing it the right way (via the indexer) and for other components as well
Oh, it allows to set :id
or whatever represents the ID from the real ID in the tempid mapping?
Assuming the server doesn't do anything but create a real ID and store the rest as-is, that makes no-effort transactions possible; the client doesn't have to do anything else at all unless they fail on the server side
(Mmh, parinfer is cool. Comment the last line of a function with a lot of )))))))))
out and it just moves the parens up to the last line still in use.)
added examples on delayed loads and optimistic commits https://github.com/omcljs/om/wiki/Om-Next-FAQ
If I see something like this TaggedValue
in the transaction response data, the client hasn't properly handled the transit response, right? This fragment passed to the send callback and :id-key
doesn't work: :tempids {[:snippet/by-uuid #object[Object [TaggedValue: om/id, ab6596ec-e154-429b-9fba-7f6a03ed619a]]] [:snippet/by-uuid ab6596ec-e154-429b-9fba-7f6a03ed619a]}
@dnolen: Actually... shouldn't the CLJS version of om.transit/reader
also use ReadHandler
?
requires none of the craziness that Relay & Falcor are pursuing due to lack of HTTP Caching narrative
turns out ident migration is a great time to prune the application state of unreachable information
is ident migration moving data to ident tables in db->tree? if not when does that happen?
Ah, of course. And migrate happens for everything returned by the server, so when e.g. {:list/one ... :list/two ...}
are returned, it rebuilds and all people that aren't returned anymore disappear.
I see, and what initiates that process? the send function calling the merge callback? So build the data tree by following refs, then merge in new unnormalized data, then renormalize?