You're not missing anything. This is a fundamental issue in Om right now
and I've been designing and working on a fix. Basically in the very near
future a component will be able to access something in the application
state without needing a parent component to pass it in from above.

The idea is that a component will be able to get its data directly from the
app state with something like (om/get-shared owner [:app-state :foo]).

Still working out the details, but this work is happening in the
`ind-components` branch. When it's finished there'll be an accompanying
nested tab view example - one of the cases that suffers the most under the
current system.

David


On Wed, Apr 9, 2014 at 6:33 AM, Daniel Kersten <[email protected]> wrote:

> Hi,
>
> I'm trying to figure out the best way of structuring complex applications
> in Om and I've hit a bit of a brick wall that I'm hoping someone can help
> me with.
>
> I like the concept of cursors - narrow down the application state to what
> the individual components actually need and allow them to read and modify
> only that.
>
> The problem I'm having is that I don't know how to structure my state so
> that the correct components have access to everything they need. Its easy
> if each component only requires a strict subset of its parent, which is
> often the case, but not always. I've hit a scenario where a component needs
> access to two very different branches of the app state and I'm not sure how
> to pass it to the component that needs it.
>
> As a (contrived) example, imagine you had an app for displaying orders in
> an online store and the application state is something like this:
>
> (def app-state (atom {:items  [{:type "book" :price 123} {:type "cd"
> :price 200}]
>                       :orders [{:date xxx :type "book" :count 3} {:date
> yyy :type "cd" :count 1}]
>                       :filter "book"}))
>
> You can imagine that in a real application the :items and :orders branches
> may be much deeper.
>
> Lets say I now have two components, one displaying the items (so it is
> passed a cursor with path [:items]) and one displaying the orders (so it is
> passed a cursor with path [:orders]). What if I now only want to display
> items and orders where the type matches the filter?
>
> I have a few options:
>
>    1. Restructure the app state in a way that gives each component access
>    to what it needs. This is not ideal as it means that I'm modelling my state
>    after how its being rendered rather than how its being processed and makes
>    it very application specific.
>    2. I can propagate the additional values down the component tree (eg
>    using the :state parameter to build), but this means that every other
>    component before the one that consumes it must now do additional work that
>    it shouldn't need to know about (couples the parent components too tightly
>    to the child one)
>    3. Similarly, passing it in opts is not ideal as it has the same issue
>    as #2, with the added caveat that the component also won't rerender on
>    change.
>    4. I can store the value in component local state and update it
>    through a core.async channel. This works well in the example above, where
>    one or two simple values need to be communicated, but gets unruly when the
>    application is more complex.
>    5. I can pass the entire app state to each component (perhaps trough
>    shared state) and use transformation functions (similar to what Sean Grove
>    did in his recent slides) to transform the state into a local view for each
>    component. This means each component gets to select exactly what it needs
>    to access without worrying about what comes before or after it in the
>    hierarchy, but then you lose the benefit of cursors and automatic
>    re-rendering when something changes.
>
>
> I'm sure I'm missing something!
>
> Any tips appreciated.
>
> Dan.
>
> --
> Note that posts from new members are moderated - please be patient with
> your first post.
> ---
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/clojurescript.
>

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to