Fork me on GitHub
#re-frame
<
2017-02-13
>
kauko12:02:36

@negaduck I remembered one reason I'd heard for why clojure.spec doesn't allow you to define a spec that only allows a defined set of keys

kauko12:02:48

it's actually in Hickey's speculation keynote

kauko12:02:49

If function1's return value is given to function2, and you have a spec that defines what keys function2 requires, you CAN add extra functionality to function1 without breaking your code

kauko12:02:26

If you have a schema that says function2 can only get these keys, and you add functionality to function1, your code will break

kauko12:02:33

even if the changes have nothing to do with function2

kauko12:02:38

This makes the most sense (to me at least), when you think about versioning libraries. You can add stuff without breaking compatibility, but removing things requires extra attention.

kauko12:02:55

This is actually most of what Rich talks about in the keynote

negaduck13:02:23

@kauko: added that video to my watch list, thank you

kasuko14:02:25

@witek I am also trying to figure out this same issue. The video https://www.youtube.com/watch?v=B1-gS0oEtYc got me half the way there. I like the idea of using CQRS with event sourcing to implement commands which are like re-frame events, this flows to a queue which is then handled by a command processor (re-frame’s event handlers) which will then modify the state (in my case an actual database) where I am stuck is getting the data to naturally flow out of the database reactively so I could then inform the clients via a websocket or something. I keep thinking rethinkdb may be the answer but I would have to only use it on the server side so it may take a bit away from the power of rethinkdb.

kasuko14:02:10

I know people have mentioned datascript but I don’t think that will work for me in this case because it may become a large database

kasuko14:02:06

I’m currently looking into postgres async notifications to see if those will work at all https://yogthos.net/posts/2016-11-05-LuminusPostgresNotifications.html

kasuko14:02:53

The reason I am doing this is I am interested in making a game simillar in style to http://urbandead.com and I think the command query separation would make things much more simple as there really is that nice seperation between actions which modify the game state and queries that just read the game state. Then since this is a game allowing the updates to the client to be real time instead of needing to poll a read-only query api would be a much better user experience!

ikitommi14:02:15

we have done similar architecture with re-frame, kekkonen & datomic (and web sockets). There are both command and event/efect-handlers in the back. Backend needs a bit of state to keep track of the remote subscriptions. But, data flows nicely between layers. For postgresql, there is the bottled water to extract the tx-stream. Was quite unpolished year ago when we last tried.

kasuko14:02:58

@ikitommi I was looking into Datomic since I knew Datascript had reactive queries but I didn’t see anything. Do you have any further information about how you got it to work with Datomic. Or even what I should google to find out?

ikitommi07:02:28

kasuko: reactive queries? Cool, didn't know that! Datomic has peer sync & the tx-log has an api. Low-level so, one has to build on top of those. Eventing works also at app-level, commands return side-effects as data, the return pipeline (interceptors) emit them.

negaduck14:02:56

I stored an HTMLAudioElement in an atom and want to add it to the div: [:div @audio]. I get an error:

Error: Objects are not valid as a React child (found: [object HTMLAudioElement]). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons.
Any way to make it work?

hkjels15:02:20

it’s exposed in reagent

negaduck15:02:25

@hkjels, sadly, [:div {:dangerouslySetInnerHTML {:__html @audio}}] just inserts [object HTMLAudioElement] string

akiroz15:02:25

You can't really do that.... React works with the virtual DOM, you can't just stick real DOM objects in there. What you probably want to do is direct DOM manupulation bypassing React completely. In your case, you could render a div element, get a reference to that div element object and use something like appendChild on it.

negaduck15:02:53

@akiroz, Thank you. I refactored it (stripping down checks of existance) to (let [theaudio (new js/Audio ...)] … [:div {:ref #(.appendChild % theaudio)}]) and it works, I now switch panels and the state of audio persists.

akiroz15:02:44

@negaduck be careful there, the ref callback will be called with nil when the component unmounts...

negaduck16:02:14

@akiroz, yes, I check that, stipped it down for clarity

fossifoo19:02:18

i'm currently using re-frame and re-com for a website and everything is fine so far, but i wonder how i could most easily add a bootstrap menu

fossifoo19:02:26

i guess the "correct" way would be to throw an event on "menu-toggle" and render the menu state according to a sub, but it seems a little excessive for a simple "display only" change

fossifoo19:02:45

oh, well, everything else looked worse, i just went for the clean way

borkdude19:02:51

but I receive nil in the event

mac20:02:16

@fossifoo The alternative is a component with local state, which I think most would find OK. You can then just dispatch the event based on the choice.

fossifoo20:02:10

yeah, i looked into that too but then i have to wrap my things in a separate component and deal with all this dirty state stuff

fossifoo20:02:46

so suddenly jumping through the event/db/sub hoop didn't look so bad different

fossifoo20:02:29

now re-com/box won't rerender if it's :class cahnges 😕

fossifoo20:02:32

ah, it will rerender, just not hide

caryfitzhugh20:02:39

hello all - I am hoping for a pointer, I'd like to do something messy, but pragmatic, I want to have a subscription from the re-frame database, and when that updates, I will save it to local-storage. First subscription selects the keys I care about from the db, the second subscription pulls off the first and stores things. I quickly noticed that re-frame isn't going to calculate the subscriptions and pass them along unless someone wants to subscribe to them - which is great. But for my case, I just want to have it happen whenever those keys are updated. Any ideas? the first thought was a timer to just subscribe, but then it's always a race condition if something goes wrong in between syncing heartbeats. Any ideas? I guess I want sortof a "headless" subscription.. ?

caryfitzhugh20:02:04

oh, second idea was to put the @subscribe into the main view, as a data-tag or something, but that seems... lame.

caryfitzhugh20:02:55

meh. well - it works to just add a data attribute on [:body ] which pulls something from the stream. and yes it's hacky to do sideeffects in a subscription to save it to localstorage, but... 🙂 If anyone has any better ideas, I'll still listen! thanks

nrako20:02:24

@caryfitzhugh You might check out the effectful handlers write-up - https://github.com/Day8/re-frame/blob/master/docs/EffectfulHandlers.md#the-coeffects. Not sure where the change is coming, but I think you should be able to side-effect to local storage without putting it in the view

caryfitzhugh20:02:59

k, thanks I'll check it out

mikethompson22:02:07

Before I forget .... I read https://lambdaisland.com/blog/11-02-2017-re-frame-form-1-subscriptions and liked these suggestions (towards the end) ....

(def <sub (comp deref re-frame.core/subscribe))
(def >evt re-frame.core/dispatch)
You may too

borkdude22:02:41

@mikethompson I just used it today, but didn’t stick with it

borkdude22:02:39

I did need the @(subscribe …) today, but had to wrap it in a function and then I would use it only once anyway. No point in defining <sub for one usage.

mikethompson22:02:24

You have only have one use of subscribe in your app?

borkdude22:02:03

so I had (let [articles (fn [] @(subscribe [::subs/articles uris]))] …) with multiple usages of (articles) in the body (callbacks, etc)

borkdude22:02:11

I could have written (fn [] (<sub …)), but it only adds one level of looking up what that means for someone reading my code

borkdude22:02:20

I might use it when it’s in Re-frame proper

mikethompson22:02:59

@borkdude Right, So you already have an abstraction over subscribe. And you don't need two :-)