Structure 1
reducers
index.ts //Combine all reducers
user.reducer.ts
product.reducer.ts
actions
index.ts //Combine all actions
user.action.ts
product.action.ts
effects
index.ts //Combine all effects
user.effect.ts
product.effect.ts
selector
//Combine all selectors
user.selector.ts
product.selector.ts
OR
user
user.reducer.ts
user.action.ts
user.effect.ts
user.selector.ts
product
product.reducer.ts
product.action.ts
product.effect.ts
product.selector.ts
reducers.ts //Combine all reducers
actions.ts //Combine all actions
effects.ts //Combine all effects
selectors.ts //Combine all selectors
Why should I use NgRx? It makes applications much more maintainable and testing-friendly because it decouples Business and Domain logic from the Rendering layer. It's also easier to debug because every action in the application is a command that can be traced back using Redux DevTools.
NGRX is a group of libraries “inspired” by the Redux pattern which in turn is “inspired” by the Flux pattern. Being a little more concise, this means that redux pattern is a simplified version of the Flux pattern and NGRX is an angular/rxjs version of the redux pattern.
If you want to take advantage of single direction data flow using Store in Angular NgRx is the solution. Using NgRx store you can create your store, effects , reducers & actions in any angular app. On the other hand RxJS is used for mainly for consuming api data and creating shared services using subject etc.
For reuse and separability we require (at least) two state stores that do not interact with each other. But we do need both stores to be active at the same time, and potentially accessed from the same components. Ngrx seems to be predicated on the assumption that there will only ever be one Store at once.
I have found the first structure to suit well for a rather small app when using reducers, actions or others in several SMART components in an app.
Although it promotes the separation of concerns, I have found it rather tedious to jump between the various directories.
Usually, working with, i.e, user.reducer.ts
, would involve working with the other files: effect, actions etc. So, the 2nd approach seems a bit more tidy.
I would like to suggest a 3rd structure that may fit and one which follows the "barrel" approach in angular2:
- store
- user
- index.ts
- user.actions.ts
- user.effects.ts
- user.reducer.ts
- user.reducer.spec.ts
// the store definition file - will expose reducer, actions etc..
// for connecting those to the app in the bootstrap phase
- index.ts
With this structure, the user directory is a barrel which exposes the various logics components which can be imported separately just by importing the user, i.e:
import { reducer as UserReducer } from '../store/user';
// or
import { UserReducer } from '../store/user'
I'm experimenting with these approaches in my open source media player app - Echoes Player - http://github.com/orizens/echoes-player
As mentioned in another comment, these strategies and architecture applied to echoes player are compiled in the ngrx styleguide
I follow this guide for best ngRx practices and structure:
https://github.com/orizens/ngrx-styleguide
The second way you mentioned is the best because (quoting from the style guide):
DO create separated files in the reducer's directory for: reducer, reducer's spec, reducer's actions and reducer's selectors. Finally, use index.ts as a barrel for exporting each file's content. Why? it's easier when developing to locate each relevant class/file
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With