I've been a very heavy user of Om for the past three months, so here's my take on it.
In my application, there is a lot of data that doesn't always need to be loaded - for example, various metrics can be viewed in charts, but since there can be a lot of data points, you wouldn't want to load metrics which aren't being viewed (since there could be many dozen different metrics, yet you may only care about 3 or 4 of them). So I think this is a good example for your question.
In itself, Om does not deal with this and assumes that the entire application state is loaded at all times. As far as Om is concerned, everything is always there in a big tree structure.
But since Om lets you update the state easily through cursors, it is easy to update sub-trees when needed. So there are two very similar approaches that I've tried out:
1. If you have data where you basically select one of a collection datasets (eg in my application, if I can only chart one metric at a time), then you can have an end-point in the tree for this data and you attach the currently selected data when it is needed, swapping the old for the new. You can easily do this with an om/update! command. It is also easy to then send the old data to the server while the new data is loaded into the state, if you have changes you need to keep in sync (om/transact! gives you the old value).
2. I have experimented with creating Om components that read the value of their cursor for some sentinel value (maybe nil or a special keyword or something) that tells it the data is not loaded, which then requests the data from the server before passing it to its child component for consumption (perhaps throwing up a loading indicator in the meantime). You can then also implement logic to unload data again (maybe a timeout after the child stops using it). This works quite well for me.
A possible improvement on #2 that I want to try out when I get a few hours is to make use of Clojures lazy sequences, rather than using a sentinel value to implement lazy loading. It seems like a natural fit, but I have yet to try it.
There are, of course, many other approaches one could take (eg, keeping track of what's loaded in a collection instead of using sentinels), but I have not tried any others.
So I guess, in summary, no, Om doesn't deal with this for you, but it gives you the tools to build it yourself to suit your needs. Personally, I like it this way because I know my access patterns better than Om does.
I saw some stuff about cursors as a way of displaying/modifying only a part of the global state. But it wasn't clear to me whether this is a formalized way of only loading part of the global state, or if cursors still require that the entire underlying "global state" is loaded into memory.
--
To give more background, let me give more specifics over what I'm thinking about when I ask this.
I've been working on a JS accounting app. One thing about accounting is that the balance of an account is dependent on every prior transaction that the account has ever had. So modeled in functional terms, it seems like you'd have to make this a tree of depth "N" where N is the total number of transactions in the account. It seems like you have to model it this way to get the data dependencies right (a change in an early transaction affects every subsequent transaction).
A functional approach with such a deep tree seems to break down (at least from the relatively little I know about Om). For one, I don't want to have to load every transaction into memory. Even though the most recent transaction depends logically on the first one, I don't want to be forced to load the first one just to show the most recent one. One possible way to work around this is to collapse all transactions prior to the ones I want to display into a single "fake" transaction that stores the accumulated balance as of this point. But now my in-memory model has to differ from my real model, and as the two diverge things start to get more complicated.
A bigger problem: I can't think of a good way, with this design, to indicate to the data layer which transactions the UI actually cares about and wants to have loaded into memory. If the tree has only one logical root (the most recent transaction) and is logically N transactions deep, how does the UI indicate which of those N it actually cares about? Maybe Om cursors can do this somehow?
I've been using a more traditional mutation-based/observable design, which seems to be working well. The UI can "subscribe" to certain transactions/balances, and this serves as a signal to the data layer about what needs to be loaded and what derived values need to be kept up to date. The data layer can be smart about how many transactions it actually needs to load to compute what the UI cares about.
I feel like a lazily loaded datastructure would solve this problem - you only need the last k transactions, then it only loads the last k transactions...
With regard to Om or Clojure I'm not sure of the specifics of such an implementation, but doing something like that with other languages that have functional programming support is one of the Major Selling Points.
No, you are still free to organize your application state however you wish. For example, our app dynamically pulls in content as you browse from feed to feed and use infinite scroll. It's up to you to decide what to fetch when, and what to cache/discard as the user navigates around.
If your application state is large but you only care about a few parts of it at a time (a few "cursors") how does Om deal with that?