This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-27
Channels
- # admin-announcements (3)
- # beginners (26)
- # boot (12)
- # cider (1)
- # cljs-dev (13)
- # cljsjs (101)
- # cljsrn (5)
- # clojure (64)
- # clojure-android (1)
- # clojure-gamedev (1)
- # clojure-greece (23)
- # clojure-nl (9)
- # clojure-poland (2)
- # clojure-russia (3)
- # clojure-spec (11)
- # clojure-uk (159)
- # clojurescript (19)
- # component (1)
- # core-async (2)
- # cursive (2)
- # datascript (1)
- # datomic (2)
- # devcards (1)
- # events (1)
- # funcool (1)
- # hispano (1)
- # hoplon (24)
- # immutant (12)
- # jobs (1)
- # keechma (18)
- # lein-figwheel (2)
- # leiningen (2)
- # off-topic (8)
- # om (23)
- # onyx (4)
- # planck (26)
- # re-frame (149)
- # reagent (6)
- # ring-swagger (9)
- # spacemacs (1)
- # specter (33)
- # spirituality-ethics (11)
- # testing (10)
- # untangled (335)
- # utah-clojurians (3)
- # vim (3)
- # yada (46)
Does anyone have any advice for working with multiple related collections in re-frame? I'm finding myself writing a lot of helper functions in my handlers.cljs that feel a bit excessive. My leading guesses are that I should re-examine my data structure or that I'm missing some key abstraction/pattern.
right now I have something like
(def db {:words
{0 {:id 0 :word "Foo"...}...}
:definitions
{0 {:id 0 :word-id 0 :entry "Bar"....}....}})
and I end up having lots of helpers like get-word-by-slug
, all-words
, words-by-slug
, etc. and still I end up writing more helpers because now I need words-by-keywords-with-definitions
etc.Is it that you are joining one dataset with another?
If so, this can be very useful: https://clojuredocs.org/clojure.set/join
@mikethompson: you are my hero lol.
clojure.set/join is a very under appreciated function 🙂
I know this is only tangentially related to re-frame, but can I just say that the node ecosystem is very nutty?
I believe in being very tolerant of criticism directed elsewhere 🙂
Some ui state really is ephemeral, and shouldn't have to be managed the same way other app state is.
We tend to just use Form-2 components, which have their own local ratoms
But I don't know that much about redux-ui
Perhaps I misunderstand what it gives you
It's a really simple thing, but a really good idea, IMHO. It's basically a bit of middleware that manages ephemeral UI state.
So for instance I am writing a little thing that lets people edit svgs and drag their elements around, at the moment.
I care, in the long term, about where users position the elements (i.e. I will save that to a persistent store at some point)
I'd really rather not mix those concerns - one is the data I care about, and the other is just stuff I need to know for UI purposes.
I could put things like "selectedElement" and "dragging" in the same place I put the rest of the data, or I could manually mount a separate point in the state atom, and manage it, even though I won;t care about it after the compnent is unmounted (more book-keeping to get rid of it)
And it keeps track of which component the ui state is for, etc., so all I have to do is call a function called updateUI with a key and a new value, and I don;t have to worry about which component is setting that ui state. But it still winds up in the main store, so it doesn;t break thins like time travel, loading states, etc.
I'm very deep into writing something for a client at the moment, and it's the first time I've ever used ES6-7, Babel, Webpack, redux, etc., so that's about all I'll be doing for the next week or so. But once I'm done with that I'd be happy to help add something for ephemeral ui state. I'm enjoying writing redux, but... the amount of boilerplate involved is irritating, Immutable is nice but syntactically annoying, and.. I'm pretty sold on clojurescript for my own stuff at this point.
Btw, the thing I am writing would be very nice in re-frame, I think, and is a lot of fun to write (unfortunately it has to be in js- even using ES6 is pushing it with this client.)
The thing I realized early on is that svgs are just part of the dom, and you can treat them just like you treat any other dom element (as long as you don't care too much about performance.)
So I wrote this thing that lets you (in an inline svg) click to create new things (circles nested in circles, which makes my life easy cause circle math is easy) and then click to select them and drag them around, but won't let them overlap, in less than 100 lines of code. I think it's really cool to let people reach into an inline svg, manipulate it, and just let React/Redux/re-frame render it in response. I'm busy right now, but I'll find some time to write something like it in re-frame soon, and demonstrate the technique of reaching into an svg. It sounds really contrived, but I am actually getting paid fairly well to write something very much like that in js at the moment...
But- when I am done with this hellish death-march I'll put an exampe together- it's kind of interesting, actually.
One hint: if you're willing to pay the price (and I imagine closure would make that price rather small) you can use d3 for mouse handling.
One nice thing about that is that d3's mouse handling is aware of the svg's viewBox- that was a pleasant surprise for me.
You also need to make the svg a ref, in React terms- not sure how you do that in re-frame, but should be straightforward.
Hey @amashi I'm just about to implement an svg that has to handle clicks in re-frame, and then I came here to read, I feel lucky 😄
But really it's so much simpler than you might think- I thought I would have to write a lot of code, and.. I didn't.
@danielcompton @mikethompson I’m trying to understand dynamic subscriptions and slightly confused by the q/get-query used in the documentation. I can just pass one subscription into another to make a dynamic one right (provided I put it as the second arg)?
You can pass the result of a subscribe (a ratom) into another subscribe in the 3rd arg
so, i really never want to do this
(register-sub
::active-entity
(fn [db]
(let [depth (:depth @db)
list (:root-list @db)
cursor (:cursor @db)]
(reaction (-> list
(nth depth)
(nth (nth cursor depth)))))))
(let [a (subscribe [:a]) b (subscribe [:b] [a])
I'm a bit worried by your code above
depth
is dependent on @db
(register-sub
::active-entity
(fn [db]
(let [depth (reaction (:depth @db))
list (reaction ((:root-list @db))
cursor (reaction (:cursor @db))]
(reaction (-> @list
(nth @depth)
(nth (nth @cursor @depth)))))))
(register-sub
::active-entity
(fn [db]
(let [depth (subscribe [:depth])) ;; <----- changed across. i assume a subscribe exists
list (reaction ((:root-list @db))
cursor (reaction (:cursor @db))]
(reaction (-> @list
(nth @depth)
(nth (nth @cursor @depth)))))))
This is all about to get dramatically simpler and more elegant in v0.8.0
See: https://github.com/Day8/re-frame/issues/170using a fn like this
(register-handler
::state-from-conn
(fn [db [_ conn]]
(let [root (posh/pull conn '[*] (:root-eid db 0))
path (:path db :node/children)
vdepth (:visible-depth db 4)
errthin (posh/pull conn `[:db/id {~path ~vdepth}] 0)]
(merge db
{:root @root
:depth 0
:cursor (vec (for [i (range vdepth)] 0))
:root-list (followpath [path ALL] :db/id vdepth @errthin)}))))
basically turns a graph housed in datascript into a 2d matrix for display and navigation
is there a smarter way to correlate two db’s than to have one firing into the other through regular dispatches
I've not tried to do this, I'm afraid
The posh list might be the best place to ask
I’ll keep it up this way, see if it pans out. Thanks for the tip on dynamic subscriptions
Have you asked that the right way? "Trigger a dispatch to a subscription" ... I'm not sure what that means
Are you saying, you want to "watch state".
And when the state in app-db changes then dispatch
The closest thing I've got is https://github.com/Day8/re-frame/blob/master/src/re_frame/middleware.cljs#L198-L236
But you have to apply that as middleware to the right handlers.
(the handlers likely to make the changes to the data)
yeah, I was just wondering, rather than fire the additional dispatches from the handlers — just fire the dispatch as the result of a changed value. So that way if there were like 3 handlers than all changed some value in app-db, but I wanted to fire the same other event as a result of that value changing, I could just have a watch set up
Yeah, I understand. I've been wondering about this area. re-frame is essentially an event driven framework. Things happen because of dispatch.
And, at the moment, dispatches tend to happen because of external actions.
Users clicks buttons, or a websocket delivers data
I have been considering (without resolution) the notion of dispatches happening because of internal reasons
There could be two kinds of "internal" triggers: - events - state changes
Ie. a way that you can say .... when this event is dispatched, then also dispatch this other event(s)
a way you can say ... when this state changes, then dispatch this event(s)
(subscriptions are another process completely. They are just a way to transport data from app-db to views. They are reactive. Never imperative. They can never cause a dispatch)
But if any of this makes it through it will be in version 0.9.0
BTW, if you understand posh, I'd love for you to look over what is coming in 0.8.0 (just around the corner) ...
https://github.com/Day8/re-frame/issues/174 https://github.com/Day8/re-frame/issues/170
I've got a feeling that both of these features might work in well with DataScript/posh. But I won't have a chance to look much into posh. So if anyone else could ... and knows of any tweaks I could make to make it even easier, I'm all ears
v0.8.0 will be out within a week
I’m already using re-frame as a sort of hand-rolled transactor so I can have a history of past states of my datascript db
Posh is nice because it always returns a reaction, so I’ve been making a bunch of subscriptions that take a posh conn, and return the value of a posh query or pull
the slight pain is that I have to pass that conn throughout my app, into every subscription and handler that might be part of a chain that will need it
but that seems like it is just not fully grok’ing form2 components and what should get passed through.
this might be relevant — I’m currently running into a challenge where, I have a list of eid’s in a reframe app-db, they get their xy coordinates based on their position in there, but the eids get passed to a posh query to return the value of their cell. When I change the grid in the app-db state, I’m not able to get the cells to re-render. Does this sound like a posh/re-frame challenge, or just something simple I’m missing about re-rending components.
Too hard to say from that brief desciption 🙂
Ok, so, the question is mostly, when you pass a child component an atom as a value, should that atom be passed into the inner function or not?
The params given to the outer fn, should be the same as those given to the inner
Always
Have you read through the tutorials on Reagent down the bottom of this page? https://github.com/Day8/re-frame/wiki#reagent-tutorials
so the thing is, what I’ve been doing is wrapping the posh’d conn inside an atom, which is why I didn’t want to pass it into the child components, because I only wanted the value from when the form was created — should have been more explicit on that
that’s why that atom was something I had take out of the arguments that got passed through
basically, when passing through the datascript conn, I only want it called once per component instance
anyway, figured it out, had been a bug on my end, isn’t related to how one would normally tie posh and re-frame together
Any opinions on how to have user authentication along with passphrase storage in a database on re-frame?
@dijonkitchen: we use email/password to get a JWT token from an api, and store that JWT token in app-db & local storage... JWT token has a timestamp claim so the api gets to set token expiry policy, and we don't store the primary auth secret (password) anywhere
@mccraigmccraig: I'm interested as well in this! Are you able to share any code samples about it? 🙂
In general since a while I've been wondering why there aren't more pre-packaged user authentication solutions around
@nilrecurring: i use buddy for creating/validating the JWT tokens https://funcool.github.io/buddy-auth/latest/#signed-jwt ... it's dead simple, and you can put whatever you like in the claims, though if you put anything sensitive in there you should use an encrypted token rather than just a signed token
@mccraigmccraig: thanks! I'm already familiar with JWT, though I never implemented it in Clojure yet. The buddy docs look super good too.
@nilrecurring: i can show you my re-frame handler code too, but it probably doesn't make much sense outside of the context of my application
Yea, most likely. I'm still searching for a nice way to interact with my APIs too. I find going the cljs-http way and defining 3 handlers for every call quite verbose ATM