A question about view bindings

26 views
Skip to first unread message

Aleksey Kladov

unread,
May 3, 2014, 3:43:37 AM5/3/14
to enf...@googlegroups.com
Hello!

I have an app-state atom, which holds a map with all state of the app, and a bunch of bound views, each of which depends on a subset of the keys of the app-state. As I understand, every `swap!` of the app-state will cause all views to re-render, which is needless, because only a subset of views needs update. Is there an easy way not to cause unnecessary redrawings? My guess that it should be some kind of Om's cursors (https://github.com/swannodette/om/wiki/Cursors). 

Alexey

Creighton Kirkendall

unread,
May 3, 2014, 7:53:39 AM5/3/14
to Enfocus
Aleksey,
Enfocus' binding mechanism is pretty smart and was designed to only render what needs to be rendered.  However I think we could improve it quite a bit.  I recently added support for lenses and with some modification to the rendering algorithm we might get a significant improvement.  Can you post a gist of your structure and how the views interact with it and I will see what I can do.

Creighton


--

---
You received this message because you are subscribed to the Google Groups "Enfocus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to enfocus+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Aleksey Kladov

unread,
May 3, 2014, 3:23:45 PM5/3/14
to enf...@googlegroups.com
Here is the gist: https://gist.github.com/matklad/d1ad3375945ad21de97a
To clarify, it's a toy app, and I don't have noticeable performance problems at the moment.

App state is a single atom that consists of several fields and a timer. The latter is my main concern, because it ticks every 200 ms and it seems wasteful to call render functions for the entire app, while the only thing which needs updating is a small loader. 

There are two files in the gist ('works.cljs' and 'broken.cljs') because I hit a bug (or at least an unexpected behaviour) =)

The natural design is to split the app into several views(`render-result` and `render-loading`) responsible for subsets of app state. This boils down to binding several render functions to the app atom (and this is the place, where lenses can help performance). However, only the last binding seems active (marked ;;BUG in the gist) =( 

So the working solution is to combine all render functions into one =)




--

---
You received this message because you are subscribed to a topic in the Google Groups "Enfocus" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/enfocus/gdgrg9XhvGw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to enfocus+u...@googlegroups.com.

ckirkendall

unread,
May 3, 2014, 10:30:16 PM5/3/14
to enf...@googlegroups.com
Aleksey,
I created a slightly modified gist that uses a very simple lens.  I will add one with later with a complex lens that will leave your app data unaltered.  If you use the current snapshot out on clojars the bind-views will only fire is the lens data has changed.


Creighton

ckirkendall

unread,
May 5, 2014, 12:59:09 PM5/5/14
to enf...@googlegroups.com
Aleksey,
I added a more complex-lens example.  In contrast to the name the setup is actually very simple.   Enfocus now support the use of the Fresnel lens library (https://github.com/ckirkendall/fresnel/blob/master/src/fresnel/lenses.cljx) for control view bindings.  Mapping are basically a chain of lenses.  In most cases in clojure we recognize lenses as a set of keywords like [:data :a :b] that represent a path in an associative structure.  Fresnel adds a much move robust view of lenses.  While supporting keywords and composition through vectors like traditional Clojure paths, it also provides the ability to define custom lenses that can transform to an from the origin data.  Below is a very simple lens definition that I used to scope your map so that rendering algorithm would only take into account a subset of keys when checking if rendering is needed.  

(defn sub-map-lens [kys]
(reify Lens
(-fetch [this value] (select-keys value kys))
(-putback [this value subvalue] (merge value subvalue))))
 
(defaction home []
".result-wrapper > .loader" (bind/bind-view app render-loading [:timer]) ;; BUG
".result-wrapper" (bind/bind-view app render-result (sub-map-lens [:state :advice])))


Here is the full gist: 

Creighton


Aleksey Kladov

unread,
May 6, 2014, 1:20:00 PM5/6/14
to enf...@googlegroups.com
I've just tried this out and it is working really nice! Binding views to different dom elements helped with aforementioned issue.

I think that with such lenses Enfocus can be seen as React with plain HTML insted of JSX, which is a huge win :)


Aleksey Kladov

unread,
May 6, 2014, 1:25:24 PM5/6/14
to enf...@googlegroups.com
Looking forward to see a new snapshot on clojars, because installation via lein-git-deps was rather messy.

Creighton Kirkendall

unread,
May 6, 2014, 1:28:21 PM5/6/14
to Enfocus
Aleksey,l
Enfocus view binding certainly give you a similar feel to react and in most cases the same level of performance.  I designed them to be flexible enough to build the same programming model.  Kioo is another library I maintain that compiles enfocus like transforms directly into react nodes.  It is in essence a replacement for JSX directly.  I think there are some benefits to the virtual dom but overall enfocus still provides a lot more flexibility in model than kioo.  I will push the snapshot asap (I thought I already did that, oops)

Creighton


--

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

ckirkendall

unread,
May 6, 2014, 2:13:00 PM5/6/14
to enf...@googlegroups.com
New snapshot is up on clojars.

Creighton
Reply all
Reply to author
Forward
0 new messages