With useDispatch I get access to dispatch method. I can implement async function inside useEffect hooks and then call dispatch when I need. This pattern is described here.
Does it mean that (in project with only functional components) redux-thunk is obsolete now?
Related
I used "'socket-io-client'" in my project. I want receive message in "'vue js'" so i want use Observable method to Observable upcoming message.
Could you please more elaborate into the following questions ??
1 - react-redux is already provides the
connect(mapStateToProps, mapDispatchToProps),
Then why there is use of middleware and redux-thunk,As per my
understanding this connect function would suffice to get the
state from the store and dispatching the events from the
component?
With plain Redux functionality, your action creators must be plain object and hence you cannot make async calls in action creators or dispatch multiple actions from one action creators, middlewares are useful here
According to the docs:
Middleware is the suggested way to extend Redux with custom
functionality. Middleware lets you wrap the store's dispatch method
for fun and profit. The key feature of middleware is that it is
composable. Multiple middleware can be combined together, where each
middleware requires no knowledge of what comes before or after it in
the chain.
The most common use case for middleware is to support asynchronous
actions without much boilerplate code or a dependency on a library
like Rx. It does so by letting you dispatch async actions in addition
to normal actions.
redux-thunk lets the action creators invert control by dispatching functions. They would receive dispatch as an argument and may call it asynchronously. Such functions are called thunks. Another example of middleware is redux-promise. It lets you dispatch a Promise async action, and dispatches a normal action when the Promise resolves.
You might look at the following example to understand how to use redux-thunk to make async calls
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.
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?
Namely, what are the advantages and disadvantages of the following approaches to building a server-side database API in Meteor?
Method-based
import Db from 'Db';
Meteor.method({"insert": (data) => {Db.insert(data)});
Subclass-based
import {Mongo} from "meteor/mongo";
class MyCollcetion extends Mongo.Collection {
insert: (data) => {super.insert(data);}
}
This problem has been solved below; there is a similar question for further reading: Meteor method vs. deny/allow rules
This is mainly a matter of ease vs control. Subclassing may be easier for simple things, and methods are more powerful.
This can also be affected by your state of mind (or affect it): CRUD vs. action-based mutation.
insert/update/remove go well with a CRUD state-of-mind, while you can associate methods with action-centric RPC mutators.
Eventually, this is a matter of personal preference, so I will try to give a short factual description and let the readers to decide based on their taste.
Subclassing
By default, Meteor automatically generates mutation methods (insert, update, remove) when a collection is instantiated.
Those methods are called behind the scenes when calling MyCollection.insert(mutator, cb) on the client side (outside client-side method code). When arriving to the server, the data are first passed through allow/deny rules and then executed.
When subclassing, you override those methods and get a 'hook' into the process.
Using methods
When defining a Meteor method you get full control of the process.
You set the parameters and the name of the method and you can perform the validation and authorization as you wish.
You can also create a method stub for client-side use, which generates optimistic UI until the results of the method server execution are received.
You can use something like a validatedMethod to get some extra validation logic and modularity to your method.
You can also prevent the creation of the default mutation methods by setting a false value for the defineMutationMethods option when instantiating the collection. You can also forbid direct mutation from the client by supplying the appropriate deny rules.
While subclassing allows you to use MyCollection.insert(...), etc. on the client, you need to call the method name with the arguments that you defined in order to mutate data.