[ANN] freactive - high performance, pure Clojurescript, declarative DOM library

995 views
Skip to first unread message

Aaron Craelius

unread,
Nov 16, 2014, 9:20:29 PM11/16/14
to clo...@googlegroups.com, clojur...@googlegroups.com
freactive (pronounced "f reactive" for functional reactive) is a new high performance, pure Clojurescript, declarative DOM library: https://github.com/aaronc/freactive

It has a syntax very similar to that of Reagent and was in fact inspired by Reagent, Om, and others.

I came up with it when I was doing some DOM programming after having spending a fair amount of time working with JavaFX (see my soon to be announced library fx-clj: https://github.com/aaronc/fx-clj). I thought Om and Reagent were very nice to work with (and actually inspired some what I did with fx-clj), but I felt from my desktop GUI experience, that I could take things a few steps further.

freactive's main advantages over existing solutions are probably built-in animations support and slightly higher performance.

Here are it's goals from the README:
  • Provide a simple, intuitive API that should be almost obvious to those familiar with Clojure (inspiration from reagent)
  • Allow for high-performance rendering good enough for animated graphics based on a purely declarative syntax
  • Allow for reactive binding of any attribute, style property or child node
  • Allow for coordinated management of state via cursors (inspiration from om)
  • Provide deeply-integrated animation support
  • Allow for cursors based on paths as well as lenses
  • Provide a generic items view component for efficient viewing of large data sets
  • Minimize unnecessary triggering of update events
  • Coordinate all updates via requestAnimationFrame wherever possible
  • Be easy to debug
  • Be written in pure Clojurescript
  • Provide support for older browsers via polyfills (not yet implemented)

Any feedback is welcome!!

I'm not sure I like the name "freactive" - but it was the best I could think of at the time. Suggestions for alternative names are welcome.

Ruslan Prokopchuk

unread,
Nov 17, 2014, 6:55:47 AM11/17/14
to clo...@googlegroups.com, clojur...@googlegroups.com
 Wow! I've awaited the moment of pure cljs solution as kontrapunkt in symphony of declarative DOM which has begun with React overture ;-)

Do I correctly understand, that freactive does not care about tag names, and I can use any ones (potentially injecting polymer or smth like pieces)? 

понедельник, 17 ноября 2014 г., 5:20:40 UTC+3 пользователь Aaron написал:

Max Gonzih

unread,
Nov 17, 2014, 9:19:29 AM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Wow! Amazing! I see some ClojureCLR code in this repository, but from brief look it's not clear why is it there. Are you also experimenting on CLR support?

Anyway, great that it finally happened!

On Monday, November 17, 2014 3:20:29 AM UTC+1, Aaron Craelius wrote:
> freactive (pronounced "f reactive" for functional reactive) is a new high performance, pure Clojurescript, declarative DOM library: https://github.com/aaronc/freactive
>
> It has a syntax very similar to that of Reagent and was in fact inspired by Reagent, Om, and others.
>
> I came up with it when I was doing some DOM programming after having spending a fair amount of time working with JavaFX (see my soon to be announced library fx-clj: https://github.com/aaronc/fx-clj). I thought Om and Reagent were very nice to work with (and actually inspired some what I did with fx-clj), but I felt from my desktop GUI experience, that I could take things a few steps further.
>
> freactive's main advantages over existing solutions are probably built-in animations support and slightly higher performance.
>
> Here are it's goals from the README:
> Provide a simple, intuitive API that should be almost obvious to those familiar with Clojure (inspiration from reagent)Allow for high-performance rendering good enough for animated graphics based on a purely declarative syntaxAllow for reactive binding of any attribute, style property or child node
> Allow for coordinated management of state via cursors (inspiration from om)Provide deeply-integrated animation supportAllow for cursors based on paths as well as lenses
> Provide a generic items view component for efficient viewing of large data sets
> Minimize unnecessary triggering of update eventsCoordinate all updates via requestAnimationFrame wherever possibleBe easy to debug

Diogo Almeida

unread,
Nov 17, 2014, 12:02:32 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
This is really cool (especially if what Ruslan said is the case). What would the best practice be for stateful effects? Do you have any plans of adding the equivalent of React's lifecycle methods?

Also, the reagent comparison doesn't work over https, because you use the http version of React.js.

Aaron Craelius

unread,
Nov 17, 2014, 2:18:36 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
> Do I correctly understand, that freactive does not care about tag names, and I can use any ones (potentially injecting polymer or smth like pieces)? 
>

Yes! It tries to work with pure DOM nodes wherever possible. In freactive, Clojurescript vectors are virtual DOM - so the "hiccup" vectors are very close to the actual DOM. Although it may not work quite yet, you should even be able to inject DOM nodes you created outside of freactive's rendering framework and it will treat them opaquely.

Aaron Craelius

unread,
Nov 17, 2014, 2:22:18 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Monday, November 17, 2014 9:19:29 AM UTC-5, Max Gonzih wrote:
> Wow! Amazing! I see some ClojureCLR code in this repository, but from brief look it's not clear why is it there. Are you also experimenting on CLR support?
>

Yes, I'm not sure if it's in a working state right now, but I was experimenting with it - I should add that to the docs. The way this started actually is I wanted some reactive atoms for JavaFX. I also have done a lot of work with WPF - see my ClojureWPF: https://github.com/aaronc/ClojureWpf - so I wanted to integrate it there too, but alas... I'm mostly moving away from .NET these days... but I started out as a ClojureCLR dev.

Ruslan Prokopchuk

unread,
Nov 17, 2014, 2:27:17 PM11/17/14
to clo...@googlegroups.com, clojur...@googlegroups.com
I've played a little bit with freactive today, and investigated this idea with using polymer components — it works! I'm unsure of right usage of rx, especially on conditional rendering — (rx (if @state ... does autorerendering, but (rx (if (:key @state) ... does not. And there are some questions about how to structure app properly. I'm too tired to formulate them today, but bigger than performance demo examples and more documentation are welcome, because I'm very enthusiastic to use freactive in real projects!


понедельник, 17 ноября 2014 г., 22:18:45 UTC+3 пользователь Aaron написал:

Shaun LeBron

unread,
Nov 17, 2014, 2:32:18 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Sunday, November 16, 2014 8:20:29 PM UTC-6, Aaron Craelius wrote:
> freactive (pronounced "f reactive" for functional reactive) is a new high performance, pure Clojurescript, declarative DOM library: https://github.com/aaronc/freactive
>
> It has a syntax very similar to that of Reagent and was in fact inspired by Reagent, Om, and others.
>
> I came up with it when I was doing some DOM programming after having spending a fair amount of time working with JavaFX (see my soon to be announced library fx-clj: https://github.com/aaronc/fx-clj). I thought Om and Reagent were very nice to work with (and actually inspired some what I did with fx-clj), but I felt from my desktop GUI experience, that I could take things a few steps further.
>
> freactive's main advantages over existing solutions are probably built-in animations support and slightly higher performance.
>
> Here are it's goals from the README:
> Provide a simple, intuitive API that should be almost obvious to those familiar with Clojure (inspiration from reagent)Allow for high-performance rendering good enough for animated graphics based on a purely declarative syntaxAllow for reactive binding of any attribute, style property or child node
> Allow for coordinated management of state via cursors (inspiration from om)Provide deeply-integrated animation supportAllow for cursors based on paths as well as lenses
> Provide a generic items view component for efficient viewing of large data sets
> Minimize unnecessary triggering of update eventsCoordinate all updates via requestAnimationFrame wherever possibleBe easy to debug
> Be written in pure Clojurescript
> Provide support for older browsers via polyfills (not yet implemented)
> Any feedback is welcome!!
> I'm not sure I like the name "freactive" - but it was the best I could think of at the time. Suggestions for alternative names are welcome.

How does it perform its dom-diffing?

Aaron Craelius

unread,
Nov 17, 2014, 2:33:12 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Monday, November 17, 2014 12:02:32 PM UTC-5, Diogo Almeida wrote:
> This is really cool (especially if what Ruslan said is the case). What would the best practice be for stateful effects? Do you have any plans of adding the equivalent of React's lifecycle methods?

So I plan to write more about this soon as I have it all more or less worked out in my head.

Briefly, :on-show and :on-hide are "lifecycle" callbacks - I intend to rename them to something like :did-mount and :will-unmount respectively. The only other lifecycle callbacks make sense in freactive's update cycle are :will-mount and :did-unmount - but I'm not even sure there is a use case or it's a good idea. freactive tries to manage state in a different way that is fundamentally tied to IDeref watches (and invalidation watches which aren't yet documented). Input definitely welcome as these facilities are developed.

As for state transitions, they will be based on the "data-state" attribute and have :on-state and :after-state callbacks. The recommended way will be to use a "state-machine" ref bound to :data-state - I also have this more or less worked out in my head... more details soon.


>
> Also, the reagent comparison doesn't work over https, because you use the http version of React.js.

Fixed! http://aaronc.github.io/freactive-reagent-comparison/

Aaron Craelius

unread,
Nov 17, 2014, 2:40:04 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Monday, November 17, 2014 2:32:18 PM UTC-5, Shaun LeBron wrote:
> How does it perform its dom-diffing?

So, it does not actually do diffing. It is very close to being able to, but if this is added it will be sort of an extra optimization as opposed to a "core" algorithm.

Instead of diffing, changes are bound directly to the site they are to be applied using rx's and atoms directly on attributes, style properties, text nodes and DOM nodes. So, changes are detected and applied more locally so there is in most cases very little to diff.

The only case where it might be needed is for large collections, but that's where the "items-view" or "collections-view" comes in (more on this coming soon I hope) - which will be much more scalable than diffing.

All this is how any serious desktop GUI framework does it (like Qt/QML, JavaFX, WPF) and freactive is just trying to emulate that.

Does that make it clear?


Jamie Orchard-Hays

unread,
Nov 17, 2014, 2:41:37 PM11/17/14
to clojur...@googlegroups.com
I kind of like it. For some reason it made me think of Professor Frink, which brings me a smile: http://en.wikipedia.org/wiki/Professor_Frink

Here's what you get googling for "freactive"

https://www.google.com/search?client=safari&rls=en&q=freactive&ie=UTF-8&oe=UTF-8

Aaron Craelius

unread,
Nov 17, 2014, 2:42:31 PM11/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Monday, November 17, 2014 2:27:17 PM UTC-5, Ruslan Prokopchuk wrote:
> I've played a little bit with freactive today, and investigated this idea with using polymer components — it works! I'm unsure of right usage of rx, especially on conditional rendering — (rx (if @state ... does autorerendering, but (rx (if (:key @state) ... does not. And there are some questions about how to structure app properly. I'm too tired to formulate them today, but bigger than performance demo examples and more documentation are welcome, because I'm very enthusiastic to use freactive in real projects!
>

Hope I can make the intended usage and specifics about update/invalidation behavior more clear - but probably another day as well. Structuring large apps is something we're figuring out as we go...

Aaron

unread,
Nov 17, 2014, 4:03:10 PM11/17/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Okay, this is what I want to say about structuring an app - I think the ideal way would be to have a single (rx (dispatch-state @state)) at the root of the app where dispatch-state is something like a multi-method.

Sven Richter

unread,
Nov 20, 2014, 5:21:33 PM11/20/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Hi,

I have been playing around and like it so far.

I experience some behavior here where I wonder if it is intended or if I am doing something wrong.

I have a main-page which I mount like this:
(dom/mount! root (main-page))

and which looks like this:
(defn main-page []
[...
[:div#content
    [(rx ((sess/get :current-page)))]]...
it loads the current page into the content div, this works.

Now I have one page which looks like this:
(defn sub-page []
  [:div
; ... some forms
   [(rx (di-table))]])

(defn di-table []
  [:table
   [:tbody
    (for [di (sess/get :dis)]
      [:tr [:td (:name di)]
       [:td (:host di)]
       [:td (str (:port di))]
       [:td [:button {:id (:id di) :on-click #(delete-docker-instance (:id di))} "Delete"]]])]])

It works as it rerenders when I change the state, however, it rerenders the whole page and not only the table, which I wouldn't expect. Is it possible to only rerender the table? I am using 0.1.0

Best Regards,
Sven

Aaron Craelius

unread,
Nov 20, 2014, 6:21:20 PM11/20/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Hi Niels,

It is true that this comparison is a bit stacked because basically freactive only modifies the needed attributes without needing to diff the whole structure. I'm not sure if I understand totally your other questions - maybe you could clarify a little.

Regarding diffing - in terms of rerendering whole subtrees every time reactive will not perform as well as react even if diffing is implemented - it is not designed that way. It is designed for direct to-site binding as opposed to binding that could be anywhere (thus the need for diffing). As a result - however - items/collection view type components (as in desktop GUI frameworks) will be needed when dealing with large collections - if they are used, however, the system should theoretically scale much better than a diffing system. Yes there are tradeoffs, but I believe the tradeoffs will probably be worth it. Of course, this is something for discussion and experimentation. Please keep in mind all that for me this was kind of an experiment for me and I am actually pleasantly surprised with the results.

On Thu, Nov 20, 2014 at 3:53 PM, Niels van Klaveren <niels.va...@gmail.com> wrote:
This looks pretty impressive, both in already implemented features and performance.

I can't help but wonder though if the example chosen to compare performance with React/ Reagent isn't stacked a bit because effectively all nodes are rerendered all the time ? Wouldn't this effectively nullify performance gains from different diffing behavior ? I know it's in the cards, but how is the performance difference now while only needing to rerender parts of the dom ?

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/99myJ9vLeKQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Aaron Craelius

unread,
Nov 20, 2014, 6:23:25 PM11/20/14
to clojur...@googlegroups.com
It should re-render the portion of your DOM that was in an rx that got invalidated. What does the implementation of sess/get look like?

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/99myJ9vLeKQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Aaron Craelius

unread,
Nov 20, 2014, 6:25:07 PM11/20/14
to clojur...@googlegroups.com
Btw, if anyone at the conj wants to discuss this, let's find some time this evening or tomorrow. 

Sven Richter

unread,
Nov 21, 2014, 4:13:35 AM11/21/14
to clojur...@googlegroups.com
Hi Aaron,

I took this idea from yogthos blog and the whole session namespace contains an freactive atom plus some helpers:

(ns de.sveri.dockerui.session
(:refer-clojure :exclude [get])
(:require [freactive.core :refer [atom]]))

(def state (atom {}))

(defn get [k & [default]]
(clojure.core/get @state k default))

(defn put! [k v]
(swap! state assoc k v))

(defn update-in! [ks f & args]
(clojure.core/swap!
state
#(apply (partial update-in % ks f) args)))


So I am assuming that I can nest (rx ...) calls and only the part that changes will get updated. Is that right?
This is basically what I am trying to achieve right now.

Best Regards,
Sven
> Provide a simple, intuitive API that should be almost obvious to those familiar with Clojure (inspiration from reagent)Allow for high-performance rendering good enough for animated graphics based on a purely declarative syntaxAllow for reactive binding of any attribute, style property or child node
> Allow for coordinated management of state via cursors (inspiration from om)Provide deeply-integrated animation supportAllow for cursors based on paths as well as lenses
> Provide a generic items view component for efficient viewing of large data sets
> Minimize unnecessary triggering of update eventsCoordinate all updates via requestAnimationFrame wherever possibleBe easy to debug

Sven Richter

unread,
Nov 21, 2014, 4:53:05 AM11/21/14
to clojur...@googlegroups.com
I created a minimal example from a chestnut project: https://github.com/sveri/freactive-example

The relevant stuff happens in core.cljs and session.cljs. When you run the application, add some text to the input and then click the button, the input is rerendered, which is unexpected from my side.

I hope that shows the problem I have.

Best Regards,
Sven

Sven Richter

unread,
Nov 21, 2014, 5:12:22 AM11/21/14
to clojur...@googlegroups.com
Ok, after trying out some more I got it working in two different ways:

1. Declare a separate atom for the navigation. By using two different atoms changes are only propagated to the views that each specific atom uses (so it seems).

2. The original code stores a reference to a function in the session atom like this:
(session/put! :current-page index)
And then the main view calls the function like this:
[:div#content (rx ((session/get :current-page)))]])

I did this so that I don't keep a whole html structure inside an atom. This does not work.

What works is this:
(session/put! :current-page (index))
[:div#content (rx (session/get :current-page))]])

But I am not sure if this is a good approach.

Best Regards,
Sven

Aaron Craelius

unread,
Nov 21, 2014, 9:50:45 AM11/21/14
to clojur...@googlegroups.com
Hi Sven,

So this is where you're going to want to use cursors. A cursor will isolate change notifications to the path or getter that the cursor refers to. So, either in the global scope or in a let outside of some rx you'll want to write something like (def current-page (cursor state :current-page)). Then you'll deref current page in your rx. Let me know if this works.

Aaron

Sven Richter

unread,
Nov 21, 2014, 5:15:57 PM11/21/14
to clojur...@googlegroups.com
Hi Aaron,

Thanks, now I know what cursors are good for, it works like you suggested.

Best Regards,
Sven

Aaron

unread,
Nov 22, 2014, 11:00:13 PM11/22/14
to clo...@googlegroups.com, clojur...@googlegroups.com

Regarding diffing - in terms of rerendering whole subtrees every time reactive will not perform as well as react even if diffing is implemented - it is not designed that way.

I should probably correct this - I think i was a bit tired when I wrote it and not as impressed with diffing performance as I wanted to be. Actually, although I've only done a very rough visual benchmark, I think the diffing performance is somewhat on par with React's - just no key support. Again, diffing isn't the core algorithm this library is using even though it has it - direct binding is.

Aaron

unread,
Nov 22, 2014, 11:25:48 PM11/22/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Also, after discussions with several people at Clojure/conj, I see that it is necessary to provide some more documentation about how the bindings (components) and data structures in this library work differently from existing solutions (especially React) and what the overall vision is. Here are some rough draft docs I have:

The overall design idea for "renderer-agnostic" user interface conventions is here: https://github.com/aaronc/freactive.core/blob/master/UI-SPEC.md. Several people were excited about this idea and hopefully we can collaborate to make something along these lines happen. This document may also clarify how bindings (or lightweight components) are intended to work in this system and how they are different from (but also similar to) React components. 

I had originally intended to separate out the data structures (rx, atom, cursor) and put them in a separate library shared between projects. Here's a separate "freactive.core" project with some more details on the design goals behind my implementations of rx, atom and cursor plus a few implementation details (to be fleshed out more later): https://github.com/aaronc/freactive.core. There's also more details on these data structures here: https://github.com/aaronc/freactive#reactive-change-notifications-in-depth.

I'm still not totally happy with the name "freactive". Maybe something like "synergy" or "synergy-ui"?

Btw, it was nice to meet so many of you in person this weekend!

Olli Piepponen

unread,
Nov 23, 2014, 3:05:57 AM11/23/14
to clo...@googlegroups.com, clojur...@googlegroups.com
If you are open to name suggestions, how about Fresco?

Aaron Craelius

unread,
Nov 23, 2014, 12:38:17 PM11/23/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Fresco isn't bad. I think it's better than "freactive" at least. Seems to be relatively popular for a name, but no big projects: https://github.com/search?o=desc&p=1&q=fresco&s=stars&type=Repositories&utf8=✓

On Sun, Nov 23, 2014 at 3:05 AM, Olli Piepponen <kot...@gmail.com> wrote:
If you are open to name suggestions, how about Fresco?

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/99myJ9vLeKQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.

Gary Trakhman

unread,
Nov 23, 2014, 1:21:19 PM11/23/14
to clojur...@googlegroups.com, clo...@googlegroups.com
The two best ones I can think of right now

Halogen: they're known as highly reactive elements.
Precipitate: both a noun and a verb, the solid that falls out of a solution, or to bring about such a reaction.

Other chemical-ish names considered
Enantiopure - Containing compounds of only a single chirality 
Fullerene - Bucky-Balls, they're just cool
Recycle - 'Save the trees', and also 'recycle streams' from chemical engineering. 

You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.

Jason Lewis

unread,
Nov 23, 2014, 2:20:34 PM11/23/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Cesium is the most reactive element of all... and the name isn't taken on Clojars.

Cesium will react explosively even with ice.

Jason Lewis

vox      410.428.0253
twitter  @canweriotnow

Jason Lewis

unread,
Nov 23, 2014, 2:22:38 PM11/23/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Furthermore (it occurs to me) cesium is used to drive atomic clocks... so if you're using an atom to maintain state... even more relevance. Relevance? Wait, it's Cognitect now :)

Jason Lewis

vox      410.428.0253
twitter  @canweriotnow

Henrik Eneroth

unread,
Nov 23, 2014, 2:44:49 PM11/23/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Hacker News has sort of noticed: https://news.ycombinator.com/item?id=8648491

Aaron Craelius

unread,
Nov 23, 2014, 10:45:01 PM11/23/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Glad to see all the enthusiasm about names :) If you think of others, you can let me know. Probably leaning towards something artistic sounding like "fresco" so far...

But anyway, more importantly did anyone check out the docs I just posted? In particular the UI spec one: https://github.com/aaronc/freactive.core/blob/master/UI-SPEC.md. What do people think about the idea of trying to generalize conventions for writing reactive UI's? Decomplecting state management from the underlying UI renderer, common semantics, etc...

Ruslan Prokopchuk

unread,
Nov 24, 2014, 4:35:14 AM11/24/14
to clo...@googlegroups.com, clojur...@googlegroups.com
If you want something artistic though exotic enough to be not used on github before, you can try 'nerikomi' (see google or http://nerikomi.blogspot.com/ for samples) — beautiful Japanese art of pottery where every layer of clay customized with different chemical reactions to produce beautiful patterns.

Saying about ui-spec, I really like it, but I think it should be developed in communication with one of concrete realizations — e.g. freactive for DOM. This way we will see real drawbacks and advantages of this model being used for real applications, and will have chance to advance it and refactor accordingly. But, may be it is only my approach to go up of the abstraction ladder — somebody prefer to think about ideal abstraction in advance and then implement it carefully.

At the moment I can't say if my problems with using freactive are problems of implementation or spec. Need more time to play with.

понедельник, 24 ноября 2014 г., 6:45:12 UTC+3 пользователь Aaron написал:

Aaron

unread,
Nov 24, 2014, 12:49:29 PM11/24/14
to clo...@googlegroups.com, clojur...@googlegroups.com
So, yes I agree - it is best to take something like this and see how it works in concrete implementations before determining whether it is good enough to subscribe to. In this case, there are actually two concrete implementations - freactive and fx-clj (which I'll formally announce once I get to update the docs). In my case, I actually thought of this abstraction first - because I was trying to think of API would work equally well for JavaFX as well as the DOM and other things. I wasn't even going to write the DOM version (freactive) but then after using the existing reactive DOM libs I found some things missing - especially in terms of easy, built-in animation support which I needed for my projects.

So, let's see how this model works for people as they use it. Please keep in mind that this is a very young library so this implementation is bound to have its kinks. Thanks for all those who are patient enough to play with it now and help improve it.

Andrew Rosa

unread,
Nov 24, 2014, 3:49:22 PM11/24/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Aaron,

Still need to study the more detailed docs, but from what I read from UI-SPEC the only thing I get confused about was the event/lifecycle.

Just a suggestion about the name, if there is time for that: despite of the chosen one, IMO will be a good thing unify all (potential) libraries under single name. So you'll end up with <lib>.core, <lib>.dom, <lib>.fx, <lib>.wpf. This way will be much more easy to follow the related libraries - after all, even with diferencies they will be tied by major common idioms.

Just my 2c

Jamie Orchard-Hays

unread,
Nov 24, 2014, 5:48:24 PM11/24/14
to clojur...@googlegroups.com
no way! "freactive" is way better. Way Better.

Jamie

Aaron Craelius

unread,
Nov 26, 2014, 5:11:42 PM11/26/14
to clojur...@googlegroups.com, clo...@googlegroups.com
On Monday, November 24, 2014 3:49:22 PM UTC-5, Andrew Rosa wrote:
> Aaron,
>
> Still need to study the more detailed docs, but from what I read from UI-SPEC the only thing I get confused about was the event/lifecycle.

Okay - that's something that would be platform-specific. It's still being worked out for the freactive. See: https://github.com/aaronc/freactive/issues/8

> Just a suggestion about the name, if there is time for that: despite of the chosen one, IMO will be a good thing unify all (potential) libraries under single name. So you'll end up with <lib>.core, <lib>.dom, <lib>.fx, <lib>.wpf. This way will be much more easy to follow the related libraries - after all, even with diferencies they will be tied by major common idioms.

Exactly!

Ruslan Prokopchuk

unread,
Nov 27, 2014, 1:40:36 AM11/27/14
to clojur...@googlegroups.com, clo...@googlegroups.com
I've noticed that you did not mention Items View in UI-SPEC and describe it as something orthogonal in freactive readme. Yes, it is really could be implemented independently, and yes, it must be decoupled from core. But it reveals drawback in abstract spec — how in terms of UI-SPEC model list of items should be rendered? Current model only supports full rerender, you need items view hackery to overcome this and apply changes only where data has been changed. But dynamic lists of things is so common case, so spec should contain conceptual key to solve it without additional entities such as items view with its own magic. I'm not sure I have solution right now, but I think it is thing worth to think about.

But, m.b., I am not right, and lists should stay opaque for reactive model. Don't know, let's discuss.

Aaron Craelius

unread,
Nov 27, 2014, 1:59:26 PM11/27/14
to clojur...@googlegroups.com, clo...@googlegroups.com
So, you've made a good observation about the spec - it doesn't proscribe any convention for dealing with sequences of items. The reason for this is pretty much that the DOM is the only modern UI framework that I've worked with that doesn't include something like an "items view". So, I understand that an "items view" may seem like a hackish solution, but from my perspective, it's actually the least hackish solution. I think something like React's "key" resolution is much more hackish. That said, I have actually been thinking about implementing something along the lines of what React is doing with keys because I see its use case and it wouldn't be that hard.

In any event, this is a good item for discussion.

On Thu, Nov 27, 2014 at 1:40 AM, Ruslan Prokopchuk <fer....@gmail.com> wrote:
I've noticed that you did not mention Items View in UI-SPEC and describe it as something orthogonal in freactive readme. Yes, it is really could be implemented independently, and yes, it must be decoupled from core. But it reveals drawback in abstract spec — how in terms of UI-SPEC model list of items should be rendered? Current model only supports full rerender, you need items view hackery to overcome this and apply changes only where data has been changed. But dynamic lists of things is so common case, so spec should contain conceptual key to solve it without additional entities such as items view with its own magic. I'm not sure I have solution right now, but I think it is thing worth to think about.

But, m.b., I am not right, and lists should stay opaque for reactive model. Don't know, let's discuss.

Sven Richter

unread,
Dec 1, 2014, 10:39:06 AM12/1/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Hi,

I am currently trying to make drag and drop work with freactive, but fail so far. This is my code:
[:thead [:tr
(for [col (first (:content struct))]
[:td [:div {:draggable true
:on-drag-start (fn [e] (println "dragged"))
:on-drag-over (fn [e] (.preventDefault e))
:on-drag-enter (fn [e] (.preventDefault e))
:on-drop (fn [e] (.preventDefault e)(println "dropped"))
:on-drag-end (fn [_] (println "drag end"))}
col]
])]]

But nothing happens, no matter what I try. Are there any restrictions? Should this be done in a different way?

Best Regards,
Sven

Aaron Craelius

unread,
Dec 1, 2014, 12:56:05 PM12/1/14
to clojur...@googlegroups.com, clo...@googlegroups.com
There are no restrictions on events and attributes (although some attributes may need a special handler if they don't work properly with setAttribute - please submit an issue on github). Looking at your code, maybe the issue is the event handler names - I believe the DOM events are called dragstart, dragend, etc. without a hyphen.

Sven Richter

unread,
Dec 1, 2014, 4:14:06 PM12/1/14
to clo...@googlegroups.com, clojur...@googlegroups.com
Thank you, I have done so here: https://github.com/aaronc/freactive/issues/25

Best Regards,
Sven

Aaron Craelius

unread,
Dec 17, 2014, 9:28:12 PM12/17/14
to clojur...@googlegroups.com, clo...@googlegroups.com
I've just posted gists about the items-view and observable collections proposed for freactive.

In case anyone is interested in discussing please comment on the gists themselves.

observable collections: https://gist.github.com/aaronc/0654151190b9145dd473
items-view: https://gist.github.com/aaronc/5d497aa61e27ce924178

And yes, these components would be separate modules from freactive core and dom, the observable collections could be used independently of the items-view and everything could (and probably will be) split into separate projects.

Leon Grapenthin

unread,
Dec 20, 2014, 3:18:25 PM12/20/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Hi Aaron,

I am currently experimenting with freactive. I find it quite awesome to begin with.

Here are some questions that I found unanswered:

- Why are rx-bindings not the default? It feels a bit redundant to wrap forms in (rx ...) all the time.

- What is the rationale behind the second argument "callback" (to one of :on-hide or :on-show)? I noticed that sometimes it is passed and sometimes it isn't and that I have to call it when it is passed...

Aaron Craelius

unread,
Dec 20, 2014, 7:14:25 PM12/20/14
to clojur...@googlegroups.com, clo...@googlegroups.com
Hi Leon,

So the reason for rx bindings not being default is really quite simple - freactive is not a macro framework but uses pure functions and I preferred giving more power to the user rather than doing something "auto-magically" that may not always be desired. One could write a simple macro that wraps all the relevant forms with an "rx" but I'm not sure this would be a good idea - you would lose the ability to be specific about bindings (rx's are only one type of thing that can be bound), it would add overhead (you don't need a binding on every form) and using macros can have other unintended consequences (you couldn't use pure functions that return virtual DOM - i.e. hiccup vectors). The main macro freactive provides is the rx macro which is really a thin wrapper macro which generates an instance of ReactiveExpression for its body - it is one type of thing that can be bound,  but not the only thing (atoms, cursors, etc. can be bound directly). Now, it may seem that this makes freactive more verbose than say Reagent, but this is not really true at all - you don't have to use rx's everywhere. If you just wrap whole functions/components in a single rx, you'll get something pretty similar to a React component (especially when diffing gets enabled in the next major version) - the performance will be quite good (probably similar to React). The ability to place bindings (i.e. rx's, atoms, etc.) directly on attributes or text nodes allows additional performance gains because the binding is direct and specific - you don't need to use it if it feels unnecessary, but the framework allows it and will optimize based on what you tell it. Does that make sense? Basically using more rx's may allow better performance for things like animations, but it's totally optional - you can just use one rx around the whole body of a component if you like...

Regarding transitions and callbacks, this API will change a little in the next version (the transition names will change) but the general concepts will remain the same. Right now, :on-show receives a callback, but in the next version it won't whereas :on-hide will and it will need to be called. The reason for needing to call this callback is because this callback is actually what hides/removes the element. The :on-hide transition is there so that you can apply some sort of fade effect, but if you don't call the callback, the element won't actually go away. This gives the user considerable power to screw things up (by not calling the callback) but I think it is useful to allow this so that people can apply fade transitions.

Reply all
Reply to author
Forward
0 new messages