Fork me on GitHub
#clojurescript
<
2018-12-09
>
bravilogy14:12:27

has anyone ever worked with react-spring?

bravilogy14:12:33

in clojurescript / reagent?

bravilogy14:12:18

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"]))]

bravilogy14:12:49

but it throws an error saying it can’t render a function

bravilogy14:12:15

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.

jayzawrotny17:12:01

Could anyone recommend a CLJS stream\functional-reactive-programming library?

richiardiandrea18:12:47

@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 😃

richiardiandrea18:12:36

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

victorbjelkholm42918:12:44

would be interesting to see how people are dealing with streams in the browser (so no nodejs streams, but need the same API) + clojurescript

jayzawrotny18:12:20

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.

jayzawrotny18:12:59

Thanks for the links though. I’m reading through them now.

richiardiandrea18:12:59

@jayzawrotny on the browser we use re-frame, which is as you might have read a better redux

richiardiandrea18:12:10

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

richiardiandrea18:12:22

What your app sees is just data

richiardiandrea18:12:35

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

jayzawrotny18:12:54

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.

richiardiandrea18:12:35

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

richiardiandrea18:12:58

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 😃

jayzawrotny18:12:32

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.

richiardiandrea18:12:57

@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 😃

richiardiandrea18:12:29

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 ;)

jayzawrotny19:12:11

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 😄

lilactown21:12:40

FWIW I find re-frame’s effect/coeffect pattern pretty much on par with the power and expressivity of redux-observable/saga

lilactown21:12:57

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

lilactown21:12:01

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

jayzawrotny21:12:25

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.

richiardiandrea19:12:58

@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!

sova20:12:18

@jayzawrotny i recommend tonsky/rum

sova20:12:17

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

sova20:12:44

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.

sova20:12:52

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.

sova20:12:25

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.

ckiehl20:12:29

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.

lilactown21:12:07

@ckiehl it depends on what event is. is this a DOM event? React event?

jayzawrotny21:12:27

@sova So you prefer rum to re-frame?

ckiehl22:12:09

@lilactown whoop -- my bad, DOM event. Specifically, via addEventListener('keydown', ...)

lilactown22:12:34

right, js->clj only works for simple {"key": value} JS objects

lilactown22:12:06

if you want to access methods and properties on more complex objects, you’ll want to use interop syntax. e.g. (.-key event)

ckiehl22:12:34

Ah, gotcha. Thanks

lilactown22:12:34

@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

jayzawrotny00:12:24

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?

lilactown23:12:48

there’s probably a simple state machine that represents this quite nicely