This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-09
Channels
- # adventofcode (229)
- # announcements (1)
- # beginners (9)
- # boot (1)
- # calva (11)
- # cider (14)
- # clojure (26)
- # clojure-kc (1)
- # clojurescript (46)
- # core-async (10)
- # cursive (6)
- # datomic (53)
- # figwheel-main (2)
- # fulcro (3)
- # hoplon (2)
- # hyperfiddle (1)
- # kaocha (2)
- # off-topic (11)
- # om (5)
- # quil (11)
- # re-frame (7)
- # reagent (6)
- # reitit (9)
- # shadow-cljs (9)
- # spacemacs (5)
- # vim (5)
I’m basically trying to use its Transition
component. the usage in jsx is this
<Transition
items={items} keys={item => item.key}
from={{ transform: 'translate3d(0,-40px,0)' }}
enter={{ transform: 'translate3d(0,0px,0)' }}
leave={{ transform: 'translate3d(0,-40px,0)' }}>
{item => props =>
<div style={props}>{item.text}</div>
}
</Transition>
it has 2 closure functions as children
. so I’m trying to replicate the above like so
[:> spring/Transition {:items items
:keys :email
:from {:transform "translate3d(0, -40px, 0)"}
:enter {:transform "translate3d(0, 0px, 0)"}
:leave {:transform "translate3d(0, -40px, 0)"}}
(fn [player]
(fn [props]
(reagent/as-element [:div "hello"]))]
Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
Could anyone recommend a CLJS stream\functional-reactive-programming library?
@jayzawrotny We tried rx.js but it was no buying us much - plus you need to learn all the operators. If you need to purely react, atom + watch usually suffice. For side effecting and pure pipelines we actually have come up with https://github.com/elasticpath/fonda - Very alpha but used in a couple of our lambdas at the moment. So the answer is as usual "it depends" on what you need 😃
Forgot to mention that for streams we were planning on using core.async but we will probably end up wrapping the stream API - we are on node
There is also interesting work here: https://clojureverse.org/t/cloroutine-v1/3300
would be interesting to see how people are dealing with streams in the browser (so no nodejs streams, but need the same API) + clojurescript
I am really familiar with RxJS but the CLJS wrapper I found hasn’t been touched since 2013. Same story with the Bacon CLJS wrapper yolk. Aiming for something in the browser, kinda want to re-create my goto js stack with react, redux, ramda, and redux-observable. Re-frame is the strongest candidate I’ve encountered so far.
Thanks for the links though. I’m reading through them now.
@jayzawrotny on the browser we use re-frame
, which is as you might have read a better redux
You don't really need the observable part because you have subscriptions and side-effects are handled by the http interceptor. like https://github.com/Day8/re-frame-http-fx
Right
What your app sees is just data
The only "tricky" part is when you want to wrap stateful components from the js world but that has become a very well known and understood trade-off with a lot of blog posts - you usually use the inner/outer component pattern
I’ve used it in a small prototype the other day, it’s very cool and do appreciate the intercepter layer. But what I got out of RxJS + Redux + Redux-Observable was the ability to relate two actions together over time. For instance showing a notification-like-ui when an a request was happening and updating it from seeing if “success” was in a subsequent action’s type or reporting an error if “error” was found which could close the notification.
It might be me but I found observables very imperative and side-effectful - they lead to closed-over state and callback style of programming...
I prefer to handle those things with flags and :error
maps in the state. You have a point that sometimes re-frame feels "scattered" and sometimes we do build a layer on top for cohesion. One of my colleagues is working on something to help with that as well using fonda
as base
Yep so fonda
has the concept of taps for side effecting - I can just say "stay tuned" - it is funny you bring this point up because we are spending some time thinking about this exact problem as well 😃
Ah I’m not saying this is what I should be doing with ClojureScript. I recognize it’s just the way I’m used to thinking about things. Observables aren’t perfect, but they’ve always felt natural to me. I liked modeling my domain in terms of functions that transform a series of actions over time. Re-frame does have some advantages but I have yet to learn how to model behaviors like that in a general way.
@jayzawrotny gotcha! There definitely some mind bending to do when moving to representing state as data. Trying to find the handle of my colleague on Clojurians so that it can expand a bit on that but cannot 😃
Anyways I hope you found some inspiration - just kinda wanted to share our experience / thoughts on this a bit - gotta go now thanks for chatting ;)
Alright, I’m glad something in this space is being worked on. Thanks for sharing, it at least gives me a direction to move towards 😄
FWIW I find re-frame’s effect/coeffect pattern pretty much on par with the power and expressivity of redux-observable/saga
the difference is that instead of modeling your side effects and chains as observables, you model them as effect handlers that return data, which in term can trigger further effect handlers
basically, the re-frame interceptor chain handles your pipeline of effects and you can simply write your functions as transformations of data as opposed to a bunch of Rx.js-specific code
Thanks for the explanation. I see the similarity and potential in re-frame but I guess I don’t yet understand how I would model something that waits for one event to dispatch to relate it to another event yet to dispatch at a later time. On a personal note, I don’t consider the Rx code in that example that unique to Rx. Observables are just monads with methods to describe transformations. It was fairly consistent with many other stream abstractions I’ve used including Elixir.
@davidcerezoinigo is the one working on the little wrapper of re-frame for consequential actions 👆 (don't know how to define this still 😃). No problem!
@jayzawrotny i recommend tonsky/rum
you can create components in rum that render to html via hiccup and can also be triggered-refreshes on atom changes by adding the "mixin" < rum/reactive
there is a sister library to rum called datascript that you can use to keep track of all your data in a datomic-like way on the clientside.
and if you are creating a multiple-person co-ordinated web application with a single server node, using datascript you can simply broadcast database deltas to all relevant users and have very real-time experiences in a low-latency way.
http://tonsky.me/blog/the-web-after-tomorrow/ is a nice blog post about the general ideas behind what sort of realtimeyness different parts of a page might need.
Does js-cljs
not work with Javascript event objects...? (js->clj event :keywordize-keys true)
seems to do nothing -- or I've got some user error on my end.
@sova So you prefer rum to re-frame?
@lilactown whoop -- my bad, DOM event. Specifically, via addEventListener('keydown', ...)
if you want to access methods and properties on more complex objects, you’ll want to use interop syntax. e.g. (.-key event)
@jayzawrotny this is a first pass at rewriting your Observable chain in terms of effects. I’m sure there is more that could be extracted and made more general, and/or corner cases I’m missing. But it’s a start
Thanks for writing this, it covers the use case nicely. I’m curious how a finite state machine would represent this better. Isn’t it already a finite state machine?