Organizing State In Your Angular Application
When one begins an Angular project for the first time, or refactors an increasingly growing one, it can be difficult to manage one’s state. It might intuitively seem that the state should be tied to a feature. As the app moves on, however, the state might not be tied to a specific feature or page. In addition, state by nature, as a single giant object, is global by nature. Maybe the folder/file structure should represent that. Also, it takes up a large portion of any app. It makes sense to put all-state in a single repository so that the state within the app can be transparent. Finally, for testing, state is a sizeable chunk of logic for one’s app and deserves its own module for bundling and testing purposes. In this article, we will discuss a tried and tested directory structure for managing state.
Data Access Folder/File Structure
State being a way of accessing data, an appropriate name for the folder/file tree for state makes sense to be called data-access. I personally use the name data-access in my applications, and therefore will be using it in this article. Following our philosophy, of grouping all state into the same folder, our app will look like this:
libs +-- px-illustrator/ | +-- data-access/ | | +-- code-box/ | | | +-- src/ | | | | +-- lib/ | | | | +-- +state | | | | +-- code-box.actions.ts,file | | | | +-- code-box.adapter.ts,file | | | | +-- code-box.effects.spec.ts,file | | | | +-- code-box.effects.ts,file | | | | +-- code-box.facade.mock.ts,file | | | | +-- code-box.facade.spec.ts,file | | | | +-- code-box.facade.ts,file | | | | +-- code-box.reducer.spec.ts,file | | | | +-- code-box.reducer.ts,file | | | | |-- code-box.selectors.ts,file | | | +-- px-illustrator-data-access-code-box.module.ts,file | | | +-- px-illustrator-data-access-code-box.module.spec.ts,file | | | |-- px-illustrator-data-access-code-box-testing.module.spec.ts,file | | +-- index.ts | | |-- test.ts | +-- karma.conf,file | +-- README.md,file | +-- tsconfig.lib,file | +-- tsconfig.lib.json,file | +-- tsconfig.spec.json,file | |-- tslint.json,file
Most notably, all the state-related code is contained within a single folder. By doing so, it solves all the above three issues:
- The state is global, and therefore can now be used by multiple features.
- We can run
ng test —project=px-illustrator-data-access-code-boxand it will run code specifically for this data-access feature state(i.e. code-box)
- By globalizing the naming convention, we can streamline the naming convention of all global files intended towards working towards the same purpose. Namely, our data-services, and features(which will be discussed in other articles).
- In addition, it removes the potential issue of circular dependencies. If, for instance, we have feature folder A, and feature folder B. B might need state from A. A might need the feature state of B. By keeping all of our state global, it helps us circumvent this circular dependency problem.
This is a relatively straight forward architecture. However, this article benefits the reader in two ways:
- Having the confidence that this is indeed a robust directory structure.
- Going through the motions of what an example folder structure would look like, if we play out our single directory structure.