There are a number of different models floating about for structuring web applicaitons, especially with respect to single page apps (SPAs). I think it important to differentiate a little as the underlying philosophy can affect how you use/think about the libraries being used. One example is re-frame and either reagent or om-next. For me, re-frame is much more a framework than either om-next or reagent, which I consider to be more libraries (though om-next is possibly moving more towards a framework).
Re-frame is really a type of functional reactive programming framework which uses reagent. As such, you look at state in a slightly different way than you might when using reagent or om to devleop a more traditional SPA. I’m not terribly familiar with FRP, although what I do know about it looks very interesting. One of those things on my TODO list. However, because of its slightly different approach, I would not use it as an example here.
Your quite right that the main state management functionality is tied to the component - this is the big benefit of the reagent/react model. You link your component to a bit of state in your state atom and if the values in that bit of the atom change, the system knows the component needs to be re-rendered. A very nice model.
However, once your applicaiton becomes more complex, you tend to introduce different routes to collect related functionality into functional groups and reduce the overall interface complexity. However, because your application is usually focused on a specific domain, there is usually some relationship between these routes and that relationship is frequently based around data. this could affect either the list of components which are rendered in a route or which components need to be re-rendered. However, the real challenge is in how you structure the state atom and how complex it becomes to pull out the data from that atom.
When focusinig just on components,the state atom structure is quite straight-forward. Essentially, you have a tree of data and your component will likely start consuming data at some point int he tree and work down. This works nicely with cursors and fits well with the component model.
Once you start adding routes, things quickly become more complicated. While your routes will represent different functionality pathways, they will likely have bits of data which is shared with other components. Now we have a decision. We can just duplicate the bits of data and keep a fairly clean state structure - we can still use cursors and the components in our route can just consume the state atom from a particular point. However, now we have a bigger problem - we have multiple points in our state structure which represent the same state and which can easily get out of sync - essentially, we have created an opportunity for update anomalies. We really don’t want that.
The alternative is to sacrifice the clean state structure and now have much more complex data links into our state. The model based around the cursor no longer works as we now need to retrieve data from various parts (trees/branches) of our application state. Even worse, our components are now more tightly coupled to the structure of our state atom - if we change this structure, we now need to check that the change in structure does not break other components. Life has now become more complex.