In NgRx, why are the action-types split from the actual action-class? - ngrx

I wonder why NgRx makes an extra split between the ActionTypes and the actual Action-class?
Why don't they put the ActionType straight on the class as a static property? This way you can reference the action straight from the reducer, removing some extra abstraction layer.

We released version 7.4 where this is supported.
Pull request
Docs
NgRx: Action Creators redesigned by Alex

Related

what is the use of first argument of createAsyncThunk?

I'm new in redux toolkit and I've managed state with redux toolkit lately. But the thing I don't know, what is usage of first argument of CreateAsyncThunk. I've read this article: https://redux-toolkit.js.org/api/createAsyncThunk and according to this, CreateAsyncThunk has two argument and first argument is named type :
A string that will be used to generate additional Redux action type constants, representing the lifecycle of an async request
Ok. But we never need to call or use this argument again, so why is important to name this argument? I tried adsfds insted of requestStatus after / and my project worked perfectly! I also understand it also works even without slash.
It seems it doesn't matter what you write as first argument, It always works! So what is the usage of the first argument?
In Redux, every action is identified by a unique type string. So createAsyncThunk creates three actions for you - in your case with the type strings "adsfds/pending", "adsfds/fulfilled" and "adsfds/rejected".
If you do not use "asdfds" in any other createAsyncThunk, that's a perfectly fine thing to do, but if you look at the Redux Devtools browser extension to see what is happening in your application, a string like that might make it very difficult to read.

How to provide capability like OnActivate (in Autofac) in Mvx.IoCProvider.Register

Autofac provides the OnActivated() method, which provides the capability to run any action after constructing a registered type.
Is possible to use a similar method in MvvmCross? Do you have any ideas to provide the same functionality?
It usually pays to understand the fundamentals of Dependency Injection (DI) instead of relying on particular DI Container features. Ask yourself the question: If I didn't have a DI Container, then how would I solve my problem?
Ironically, it turns out that things are usually much simpler with Pure DI.
If you didn't have a DI Container, then how would you run an action after construction of an object?
The easiest solution is to provide a factory that creates and initialises the object. Assuming the same API and requirements as the Autofac documentation implies, you could do this:
public static Dependency2 CreateDependency2(ITestOutputHelper output, Dependency1 dependency)
{
var d2 = new Dependency2(ITestOutputHelper output, Dependency1 dependency);
d2.Initialize();
return d2;
}
If you still must use another DI Container, most of them enable you to register a factory like the above against the type. I don't know how MvvmCross works, but I'd be surprised if this wasn't possible. If it isn't, you can implement an Adapter over your actual dependency. The Adapter would take care of running the action on the adapted object.
FWIW, if an object isn't in a valid state before you've run some action on it, then encapsulation is broken. The fundamental characteristic of encapsulation is that objects protect their invariants so that they can never be in invalid states. If possible, consider a better API design.

Using the constructor in order to select on the store and ngOnInit in order to dispatch from the store

My question relates to dispatching & selecting from the ngrx store.
Let's look at the following code from the official example app:
export class CollectionPageComponent implements OnInit {
books$: Observable<Book[]>;
constructor(private store: Store<fromBooks.State>) {
this.books$ = store.select(fromBooks.getBookCollection);
}
ngOnInit() {
this.store.dispatch(new collection.Load());
}
}
I would like to understand what motivated the choice of dispatching from ngOnInit and selecting from the constructor.
Can anyone please provide an explanation?
P.S. By the way, the above is sample code from the ngrx example app that can be found here: https://github.com/ngrx/platform/blob/master/example-app/app/books/containers/collection-page.ts
The constructor is executed when the class is instantiated and ensures proper initialization of the class´ fields.
This is where Angular resolves providers you may pass as arguments in your constructor.
The ngOnInit lifecycle hook is called after the data-bound properties have been checked for the first time (inputs & outputs of the component).
For a more detailed explanation see this question.
The motivation for selecting from ngrx store in the constructor and dispatching from ngOnInit as far as I understand it, is that selecting is part of initializing you component class. Since this.books$ is an Observable, it makes sense initialize it in the constructor so it is ready for use immediately after creation. Assuming the bookCollection.Load() emits a value to this.books$ you want this.books$ to be an observable of those books before an eventual value is emitted.
Since you want those values emitted to this.books$ it makes sense to dispatch the action in ngOnInit. This way you can ne certain that this.books$ is initialized.
This answer to a similar question might also be of help.
The main reason in my opinion is separation of concerns.
The constructor is the place were you define all dependencies. So in this case getting the store and than selecting a slice of it.
Dispatching an actions though is part of logic that can be separated from the dependencies (if possible).
Think of a class with lots of dependencies and lots of actions. This helps to keep things separated.
Everyone who will read the class can always look at the constructor to see what the dependencies are and is not obfuscated with any other logic.

can I dispatch an action as an array instead of an object literal?

I've tried it with a simple demonstration, and it seems to work. But just to make sure, is there anything in redux or redux middlewares that require an action to be an object with a 'type' property? I've read some tutorials that the 'type' property thing was emphasized to be a must-have.
Before:
dispatch({ type: 'DO_SOMETHING', info: 1 });
after:
dispatch(['DO_SOMETHING', 1]);
#TomW is correct - you can't dispatch arrays with a standard Redux store. It's possible to write middleware that look for arrays being dispatched and intercept them in some way. However, anything that actually reaches the reducers must be a plain object with a type field.
You may want to read my blog post Idiomatic Redux: The Tao of Redux, Part 1 - Implementation and Intent, where I discuss the actual technical limitations that Redux requires and why those exist. There's also a somewhat related discussion in redux#1813, where someone submitted a pull request trying to add the ability to dispatch multiple actions at once without actually understanding how all the pieces fit together.
The Redux documentation explicitly requires that you provide a type property:
http://redux.js.org/docs/basics/Actions.html
Actions are plain JavaScript objects. Actions must have a type property that indicates the type of action being performed. Types should typically be defined as string constants.
Furthermore, Redux appears to throw an exception in dispatch if you:
Don't have a plain object: https://github.com/reactjs/redux/blob/v3.7.0/src/createStore.js#L150
With a type property: https://github.com/reactjs/redux/blob/v3.7.0/src/createStore.js#L158
Do you have some middleware that is transforming the dispatched payload in some way?

Passing value between two components in angular2-meteor project

I am using angular2-meteor.
When I try to pass a value between two components (when the value change in the first component, create an event in second component and use this new value), I have two ways right now:
One way is meteor way: using this.autorun and Session.get.
Another way is angular2 way: using Injectable service with EventEmitter.
Which way should be prior? Or is there any other better way? Thanks
Now I used angular2-meteor a while.
Although the angular2-meteor tutorial has no example so far about using or choosing Angular 2 service or Meteor Session.
But I feel angular 2 takes the lead in the front end, while meteor makes reactivity easier and also handle all back end things.
So I went with angular2 way using service to share between components. And service is very powerful like #todd-w-crone said.
If anyone has better answer, I will switch to accept that one.
I find it practical to create a new service called App.states.ts which is accessed globally and mimics Session (get / set).
I commonly import this service to all necessary components to get or set new value such as User.status, company.profile, lastProduct, etc.
Since this service is #injectable it can also make use of other services, in case a value hasn't been set already.
This allows me to ask for a variable in a component appState.getLastModifiedItem(), then in app.states.ts I'll write this function to pass this.modifiedItem or either:
Request another service item.service.ts to fetch data
Call another function with itemCollection.findOne({...}) and return such value.
You can configure Mongo queries as you want and either store static data in appState or keep subscription items in appState.
Do take into consideration that all subscriptions handled by an #injectable within a component are imported by such component. Be wary of conflicting subscriptions between components/services.

Resources