The Anti-Pattern
Often I see code structures that couple global state to specific pages in an application. This applies to any state management library, but I’ll use redux as an example. Take this file structure:
/HomePage
reducer
saga
selectors
index
/ProfilePage
reducer
saga
selectors
index
...
This is an easy pattern to fall into, but has several problems. For example, say the profile page loads the user data in order to display it, and stores it using its own reducer. That’s fine until we need to access the user data on a different page, e.g. the HomePage. We now have two options:
-
Import the state from the ProfilePage into the HomePage, tightly coupling the two pages together.
-
Duplicate the code from the ProfilePage and add it to the HomePage
We either introduce code duplication, or unnecessary coupling, which are both considered harmful in software development. This problem is only amplified the more pages that are added. Imagine several pages all importing from each-other to get certain pieces of state. This can cause a high degree of complicated inter-connected coupling, and/or lots of duplicated hard-to-manage code.
A better way
One alternative to the above architecture is to separate your state management code from your view rendering code. Here’s an example:
/redux
/users
reducer
selectors
saga
/books
reducer
selectors
saga
/pages
/HomePage
/ProfilePage
In the above architecture, the HomePage and ProfilePage import state from the users domain instead of coupling to each-other. We no longer need to write duplicate code, and we don’t have pages coupled to other pages.
Final Thoughts
Separating your state from your views creates a much cleaner and scalable architecture. If at all possible, this anti-pattern of coupling your state to your views should be avoided.