[overhead]
Is there any overhead for a react component at runtime? If I have a single component which emits a bunch of <li>, is there any cost to having each <li> be an instance of a component which emits that <li>?
[transform cursor]
Is it OK to transform the cursor that is sent to a child component?
For example, in my app-state I have a property "left-nav-expanded? :bool". This is consumed by a generic "nav" component which wants an "expanded?" property. At the moment I have the parent component do something like
"(om/build nav (assoc app :expanded? (:left-nav-expanded? app))". Is that allowed? I want the expanded to be app state not component state BTW.
Another example of this is I have a selected-id and I want the table to add a "selected" class to the relevant row. Again, I want the selected-id to be part of the app-state (as it needs to be preserved between sub-pages) so the table has the selected-id property and the row components receive data containing "selected?". This does mean every row gets "processed" when the selected-id changes, which is making IE8 really quite slow unfortunately but I don't want to store "selected?" in the app-state on the row as the list in app-state is domain specific not UI specific. Is the idiomatic approach to add a "selected?" on each item in the list in app-state?
[Emit only components necessary or use "display" to show/hide components?]
Are there any discussions on the benefit of including (in om/root) all components but using display:none to hide the deselected ones over only including the current component?
There are obvious benefits in terms of UI state like scrolling position being preserved when using display:none but are there any performance considerations? If only emitting the components being used then the om lifecycle events are very useful for hooking in to to update the app-state for example so app-state can only represent the current working set if that is what you want.
If it helps the app will only show maybe 10% of the components at any one time.
At the moment, in IE8, using the above approach (of decorating the cursor) to select a row takes about a second on a table with 100 rows in it :(. It also takes a few seconds to draw the whole table when changing pages. I haven't profiled it yet using show/hide.
Hope that makes sense and thanks!
I'm not knowledgeable enough to answer your questions definitively (or properly format a post to this group...). But I think the om todo mvc app (1) is worth studying. For example, the "item" component renders only an "li" tag (2), yet the performance is excellent (3). I haven't done any of my own testing or benchmarking, but I feel comfortable just from seeing the performance of the todo mvc app that if there is any overhead with this approach, it's surely very minimal. I've never seen any recommendations to avoid this.
The todo mvc app also demonstrates several of the specific techniques you're asking about, like transforming cursors (4) and generating css classes for rows from values in app-state (5). These techniques seem perfectly reasonable to me.
in IE8, try clicking "benchmark 1" (1), and then clicking the "toggle-all" icon on the left side of the header row. In modern browsers, this is extremely fast. Is it slow in IE8? If not, I'd suggest comparing your strategies to those demonstrated in the todo mvc app and trying to identify what your bottleneck might be. Beyond that, from my perspective at least, it's much easier to (try to) be helpful if you can provide a a minimal code example that demonstrates the poor performance you're describing.
1) http://swannodette.github.io/todomvc/labs/architecture-examples/om/index.html
2) https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/item.cljs#L67
3) http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/
4) https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/app.cljs#L58
5) https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/item.cljs#L64
Check out the section "Browser Support and Polyfills" here: http://facebook.github.io/react/docs/working-with-the-browser.html
(om/build-all child-component (map (fn [child] (assoc child :selected? (= (:id child) selected-id) :selected-row-fn (fn [p] (om/set-state! owner :selected-id (:id p).....)) child-data)
I now do:
(om/build-the-component data
{:fn (fn [p] (assoc data :selected? (= (:id child) ...))
:opts {:selected-row-fn (fn [p] (om/set-state! owner :selected-id (:id @p)))}})
In other words, the lesson I am learning is that the cursor really wants to be domain orientated and change as little as often.
Am I right in thinking that for component instance specific immutable data (e.g is it selected), use :fn. For component class level data use :opts (e.g. selected callbacks). For global data there is always access to (om/root {:shared...}) but that isn't applicable in this case?
Thanks.
a child component, when receiving data ("props") from a parent component, will compare the data to the data it previously received. if the data has changed, the child component will re-render. the props it receives will always have been passed through the function in :fn (provided to om/build or om/build-all in the parent component). so any transformations in that function will always participate in the child component's determination to re-render (or not). for example, if your function in :fn assoc's a new unique id to the props every time it is called, the child component will re-render every time it receives props.
anything the child component receives in :opts is not evaluated for the re-render-or-not decision. if you put values in :opts, and those values have changed but the props have not, the child component will not re-render.
because of this distinction in how child components process the two, it generally makes sense to put a callback function in :opts, and a transforming function in :fn.
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.