React Redux Thunk with mapDispatchToProps - reactjs

Looking at examples of how to use mapDispatchToProps most examples follow the following pattern, a function that returns an object with dispatch as an argument:
const mapDispatchToProps = (dispatch) => {
return({
someFunc: (arg) => {dispatch(someFunc(arg))}
})
}
My question is, if all my actions are using thunk, meaning they all have access to dispatch anyway, why would i need to use the above example for mapping functions to props in my containers ?
After experimenting i've figured out another way that seems to work, however im not sure if this is best practice...
Main.jsx
import * as mainActions from '../actions/mainActions'
import * as menuActions from '../actions/menuActions'
const actionsToMap = {...mainActions, ...menuActions}
export default connect(mapStateToProps, actionsToMap)(Main)
Is there anything wrong with this approach?

Both approaches are correct and you can also use bindActionCreators when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it. Technically, that's the only use case for it.
Pulling it from the documentation, mapDispatchToProps can be a function or object.
I think your first approach is good for documentation as one can easily see the signature of the action creators you're using in your component without having to navigate to the action creator file. Other than that, I'm fine using objects(your second approach) in most cases.
Hope this helps!

Separating the concerns is a good idea and in almost all apps it would be a good idea to use Action Creators (which is what you're doing in the second example) as oppose to use plain objects (as in the first).
There are several benefits:
Easier to extend and convert if it isn't buried in an object / function
Easier to test an isolated, functional action. (Have you tried testing the first example?)
Possible to re-use - what happens if some other part of your app needs to dispatch the same action, would you cut and paste this dispatch?
Now consider 1 and 3 together, if you'd dispatched this in several places and you need to extend?
It's not just me saying this, the Redux docs covers it here: https://redux.js.org/recipes/reducingboilerplate#action-creators
That being said, they do also say that plain objects might be enough, but considering how simple action creators actually are it's probably worth making your work extensible in almost all cases.

Related

When it is React Hooks with Redux, must it be using selectors?

In the old days, when React and Redux was used, some people use selectors, some people don't.
(I think it is "reselect" npm package, but I am not sure).
However, when React has Hooks, I think we can use
useSelector()
useDispatch()
instead of all the mapStateToProps, mapDispatchToProps, connect(...)(Component). However, must we make use of useSelector()? Before, we have a choice to use selector or not to use it. Is it true that after we have React Hooks and Redux, then we have to use selectors?
Yes, you must use useSelector. And I think you have a bit of confusion there: If you were to use connect with mapStateToProps, you were always using a selector function there: mapStateToProps was that selector function, probably made off multiple sub-selectors that you might have been written inline or imported from somewhere.
You never "had the choice not to use a selector" though, if you wanted any value from the state. I think your concept of "what is a selector" is just a bit too strict.
You can use it two ways:
// in your slice file
export const someSelector = state => state.something;
// in your component file
import someSelector from './sliceFile';
// in your component
useSelector(someSelector)
or just inline:
useSelector(state => state.something)
Both of these are selectors, even when the second one looks a bit less like it.
One is just extracted into a function and the other one is an inline function. Both are totally okay to use and from a JS perspective, there is not a lot of difference between them.
As you mention reselect: reselect makes "memoized selectors", which is another concept on top of it. For that, you are free to use it or not use it, you're right there.

What is the difference between using redux-thunk and calling dispatch() directly

I'm in the learning phase of understanding redux state management and still trying to negotiate the bewildering jungle of boilerplate code and middleware, much of which I'm taking on faith as 'good medicine'. So I hope you'll bear with me on this perhaps rudimentary question.
I know that redux-thunk allows action creators to proceed asynchronously and dispatch a regular action at a subsequent time. For example, I can define a thunk action creator in my actions.js:
export function startTracking() {
return (dispatch => {
someAsyncFunction().then(result => dispatch({
type: types.SET_TRACKING,
location: result
}))
})
}
And invoke it from within a React component like so:
onPress={() => this.props.dispatch(actions.startTracking())}
My question is, what advantage does the above code confer over simply dispatching an action from inside an asynchronous callback?
import { store } from '../setupRedux'
...
export function startTracking() {
someAsyncFunction().then(result => {
store.dispatch({
type: types.SET_TRACKING,
location: result
})
})
}
which I would invoke inside my component
onPress={() => actions.startTracking()}
or even
onPress={actions.startTracking}
Is there anything problematic with accessing store directly via an import as I'm doing in the 2nd example?
There is nothing wrong doing so. From the redux-thunk page:
If you’re not sure whether you need it, you probably don’t.
The creator of redux explain the advantage of using it here:
This looks simpler but we don’t recommend this approach. The main reason we dislike it is because it forces store to be a singleton. This makes it very hard to implement server rendering. On the server, you will want each request to have its own store, so that different users get different preloaded data.
Basically, using redux-thunk will save you the store import in each action creator file and you will be able to have multiple store. This approach also give you the opportunity to write a little bit less code and to avoid spaghetti code. Many redux developer don't like to import the store and to manually dispatch because it can create circular dependencies if the code is badly separated (importing an action name from the action creator file in the reducers file and importing the store from the reducers file in the action creator file). Also, dispatching directly an action like that might break the middleware workflow, ie: the action might not be handled by a middleware.
But honestly, if you don't see an advantage to it yet, don't use it. If one day you have trouble with async actions, redux-thunk might be the answer.

What's the use of mapDispatchToProps when we can just use this.props.dispatch to dispatch action

I've been using #connect annotation for some time and decide to switch to mapStateToProps and mapDispatchToProps.
I can mapStateToProps to map store to component's props fine but wondering what's the point of mapDispatchToProps when I can just call this.props.dispatch( xxx ) anywhere.
I also see some react repos and they also do not use mapDispatchToProps
https://github.com/Hashnode/mern-starter
https://github.com/andrewngu/sound-redux
Sorry if it sounds like a beginner question.
Yes, you can certainly use props.dispatch() directly in a component. However, that component now "knows" that is part of a Redux application, because it's explicitly trying to "dispatch" things.
On the other hand, if you consistently use action creator functions, now the component is just calling things like this.props.doSomeThing(). It doesn't actually "know" that it's in a Redux app, and is more reusable as a result.
I just answered a similar question at When would bindActionCreators be used in react/redux? , and wrote a longer blog post on the topic at Idiomatic Redux: Why use action creators?.

How to dispatch multiple actions one after another

In my react / redux application I often want to dispatch multiple actions after another.
Given the following example: After a successful login I want to store the user data and after that I want to initiate another async action that loads application configuration from the server.
I know that I can use redux-thunkto build an action creator like this
function loginRequestSuccess(data) {
return function(dispatch) {
dispatch(saveUserData(data.user))
dispatch(loadConfig())
}
}
So my questions are:
When the first dispatchreturns, is the state already changed by all reducers listening for that action? I'm wondering if the two dispatch calls are run strictly sequential.
Is this approach considered best practice for dispatching multiple actions? If not, what would you suggest alternatively?
Thanks for any help!
Yes redux-thunk allows you to do as you say, and yes it is a best practice for dispatching multiple actions (one that I prefer over the alternatives because of it's simplicity). The state is indeed updated as soon as you dispatch (by the time it returns), which is why you are given a function to retrieve the state in a thunk, instead of simply a reference to the state. In that way you can alter the state with one dispatch, and then call getState() to get a reference to the new state to read from if you need to.
redux-thunk is exactly what you are looking for. I consider it very good practice.
To answer your question, indeed when the first dispatch returns the state is already changed by the called reducers.
I know its a late response :-P You can do this by using Redux-Thunk and also checkout Redux-Saga. Redux Saga provides an amazing way to handle loads of actions at the same time. Below is an example of dispatching multiple actions using Redux-Thunk
function getAndLoadSider(moduleName){
return function(dispatch){
return doSomeApiCall(someData).then(function(item){
let _item = someOtherFunction(item.collections);
let _menuData = {
name: item.name,
key: item.key
};
return new Promise(function(res, rej){
dispatch(actionOne(_menuData));
res(_item);
}).then((_item) => dispatch(actionTwo(_item)))
}
}
Above method works well for your case when one action is dependent on the first. This is a promise based approach. If you don't like to do a lots of Promise coding I recommend you go for Sagas. Check out this link https://redux-saga.js.org/docs/advanced/ComposingSagas.html where you will learn how to compose sagas. Learning curve is steep; but once you are done, Sagas will make you a ninja redux dev.
Hope this helps :-)

What is the difference between redux-thunk and redux-promise?

As far as I know and correct me if I am wrong, redux-thunk is a middleware which helps us dispatch async function and debug values in the action itself while when I used redux-promise I couldn't create async functions without implementing my own mechanism as Action throws an exception of dispatching only plain objects.
What is the major differences between these two packages? Are there any benefits of using both the packages in a single page react app or sticking to redux-thunk would be enough?
redux-thunk allows your action creators to return a function :
function myAction(payload){
return function(dispatch){
// use dispatch as you please
}
}
redux-promise allows them to return a promise :
function myAction(payload){
return new Promise(function(resolve, reject){
resolve(someData); // redux-promise will dispatch someData
});
}
Both libraries are useful if you need to dispatch action async or conditionally. redux-thunk also allows you to dispatch several times within one action creator. Whether you choose one, the other or both entirely depends on your needs/style.
You'll likely want/need both together in your app. Start with redux-promise for routine promise-producing async tasks and then scale up to add Thunks (or Sagas, etc.) as complexity increases:
When life is simple, and you're just doing basic async work with creators that return a single promise, then redux-promise will improve your life and simplify that, quick and easy. (In a nutshell, instead of you needing to think about 'unwrapping' your promises when they resolve, then writing/dispatching the results, redux-promise(-middleware) takes care of all that boring stuff for you.)
But, life gets more complex when:
Maybe your action creator wants to produce several promises, which you want to dispatch as separate actions to separate reducers?
Or, you have some complex pre-processing and conditional logic to manage, before deciding how and where to dispatch the results?
In those cases, the benefit of redux-thunk is that it allows you to encapsulate complexity inside your action-creator.
But note that if your Thunk produces and dispatches promises, then you'll want to use both libraries together:
the Thunk would compose the original action(s) and dispatch them
redux-promise would then handle unwrapping at the reducer(s) the individual promise(s) generated by your Thunk, to avoid the boilerplate that entails. (You could instead do everything in Thunks, with promise.then(unwrapAndDispatchResult).catch(unwrapAndDispatchError)... but why would you?)
Another simple way to sum up the difference in use-cases: the beginning vs. the end of the Redux action cycle:
Thunks are for the beginning of your Redux flow: if you need to create a complex action, or encapsulate some gnarly action-creation
logic, keeping it out of your components, and definitely out of reducers.
redux-promise is for the end of
your flow, once everything has been boiled down to simple promises, and you just want to unwrap them and store their resolved/rejected value in the store
NOTES/REFS:
I find redux-promise-middleware to be a more complete and understandable implementation of the idea behind the original redux-promise. It's under active development, and is also nicely complemented by redux-promise-reducer.
there are additional similar middlewares available for composing/sequencing your complex actions: one very popular one is redux-saga, which is very similar to redux-thunk, but is based on the syntax of generator functions. Again, you'd likely use it in conjunction with redux-promise, because sagas produce promises you don't want to have to unwrap and process manually with tons of boilerplate...
Here's a great article directly comparing various async composition options, including thunk and redux-promise-middleware. (TL;DR: "Redux Promise Middleware reduces boilerplate pretty dramatically vs some of the other options" ... "I think I like Saga for more complex applications (read: "uses"), and Redux Promise Middleware for everything else.")
Note that there's an important case where you may think you need to dispatch multiple actions, but you really don't, and you can keep simple things simple. That's where you just want multiple reducers to react to a single async call, and you would be inclined to dispatch multiple actions to those multiple reducers. But, there's no reason at all why multiple reducers can't monitor a single action type. You'd simply want to make sure that your team knows you're using that convention, so they don't assume only a single reducer (with a related name) can handle a given action.
Full disclosure: I'm relatively new to Redux development and struggled with this question myself. I'll paraphrase the most succinct answer I found:
ReduxPromise returns a promise as the payload when an action is dispatched, and then the ReduxPromise middleware works to resolve that promise and pass the result to the reducer.
ReduxThunk, on the other hand, forces the action creator to hold off on actually dispatching the action object to the reducers until dispatch is called.
Here's a link to the tutorial where I found this info: https://blog.tighten.co/react-101-part-4-firebase.

Resources