I'm in a problem when update store of my react redux app.
How can I make store update thenable?
As you know, all updates of states are async, so we have to use componentDidUpdate method if I do something as a callback function of state update. But these are sometimes complicated. I'd like to make this simple, by something like making them thenable method. Does have any body any idea?
The reducer function supposed to be pure so the async logic should not be there.
There are few middlewares you might be interested in:
redux-thunk allows you to have action creator that returns a function which dispatch and getState from store are injected into a normal action which means can delay the dispatch however you want. But it has limited power. (which you might not need more than that)
redux-saga use generators to explain all the side-effects and async operation in terms of data. It is more powerful than thunk, you can do complicated async interaction, for example, racing between multiple actions. But the downside is there will be more action you need to create and unpredictability caused by action dependencies.
redux-observable is claimed to be more sophisticated than saga. It is based on Rx observable stream and you can manipulate stream of actions with map flatMap filter which similar to array's method but there are more you can use. For me, it's interface looks much nicer than saga. Some might argue against the learning curve needed for understanding Rx.
Related
In my thunk, I have two dispatches in an array called dispatches which modify the Redux store. Only after both of them have completed (i.e., modified the Redux store), I want to dispatch finalDispatchCall. I tried putting them both in a Promise and called then, but I still see the finalDispatchCall being made before the secondDispatchCall has updated the Redux store.
const dispatches = [];
dispatches.push(dispatch(firstDispatchCall());
dispatches.push(dispatch(secondDispatchCall());
Promise.all([...dispatches]).then(() => {
dispatch(finalDispatchCall());
})
.catch(error => {
logger.error(
`Print out error - ${error}`
);
});
Is there a way to make sure a dispatch has completed before calling another dispatch?
EDIT (more details):
The firstDispatchCall is making an API call (returning fetch) and dispatching an action in the then statement to update the redux store. The secondDispatchCall is also making an API call (returning fetch) and dispatching two other actions in their then statements which each make their own API calls and dispatch actions to update the redux store.
I want to wait until all of this is complete before making that finalDispatchCall.
As long as firstDispatchCall() and secondDispatchCall() are sync, then redux guarantees that they'll arrive synchronously, in sequence, and that subsequent calls to dispatch() will act upon the updated state. But, if you want to be absolutely certain, you can use store.subscribe(), to kind of procedurally await all the changes you're expecting, and read the store on each change to confirm they're all there. This will actually be essential if first and second DispatchCall are async.
But, the question is whether you really need to know, from that specific thunk, when all the dispatches have landed. Redux is an event bus, and as such offers many ways to skin the async cat. It might help to understand more about the problem you're trying to solve by waiting for these dispatches in order to dispatch the last one. It may be that you don't really need to do that...
I recommend reading the Redux team's take on this exact question: "Should I dispatch multiple actions in a row from one action creator?". Especially note there:
"In general, ask if these actions are related but independent, or
should actually be represented as one action."
Newcomers to Redux often use multiple actions for what could be a single action, because they forget that multiple reducers can all listen to the same action.
I am using React and Redux (react starter kit).
I have a set of action, and when some are called, I want to dispatch side effects.
For exemple, I have a workspace that contains projects, if workspaceID in the store change, (using my action setWorkspaceId) then, the projects store will notice the change, and start execute some api call to update itself.
IN angular/ngrx, I was using Effects, so the Effect where dispatching other action when a certain action was called.
What is the redux way ? I was checking into Redux-Saga, but is there something else or already built in ?
Left alone, Redux just accumulates state from the actions it receives via dispatch, so there is no single Redux-blessed way to trigger side effects from actions.
But it supports middleware, which allows you to monitor, subscribe to and even change actions that are dispatched.
If you're familiar with RxJS via ngrx, redux-observable might be something worth looking into. It allows you to consume and emit actions via RxJS's observable type. The use case you describe of triggering an API call when a value changes would be well-suited to this.
But as you say, there's also redux-saga, which uses generators to model asynchronous logic around the consumption and production of Redux actions and other side effects. There are pros and cons to these and all the other solutions out there.
Ultimately I suggest starting with what's most familiar to you, especially if you're new to Redux.
One piece of unsolicited advice - middleware is easy to overuse. Be wary of doing in middleware and side effects that which can be achieved in a reducer.
It's easy and tempting enough to set up middleware to dispatch action B in response to action A, but if all action B does is update some state, maybe that state's reducer can just react to action A.
What is the redux way?
Use mapStateToProps to subscribe for store changes.
Then use useEffect in your function component, with workspaceID as dependency, to do some side effects (i.e calling an api).
function Component(props) {
useEffect(
() => {
// call api
}
, [props.workspaceID] // only run effect when workspaceID changes
)
}
mapStateToProps(state) {
return {
workspaceID: state.workspaceID // subscribe to workspaceID changes in store
}
}
connect(mapStateToProps, {})(Component)
I am kind of in dilemma when do we need to use redux actions and redux saga actions.
I don't mean to ask when to use redux and when to use redux-saga. But I would like to know that what scenario do we need to use redux actions when we use redux saga. Or don't I need to use redux actions when using redux saga?
Please help me understanding the use cases of redux when using redux-saga.
Not sure if this is what you meant, but just in case: the actions themselves are indistinguishable between redux and redux-saga. In both cases, an action is an object with a type, and possibly a payload. For example, this is an action:
{
type: 'DO_STUFF',
value: 3,
}
When you dispatch an action, it's first going to go into your middlewares. Redux-saga is an example of a middleware, and it can decide whether it wants to do anything with the action. If the action gets past redux-saga, it then goes to the reducers.
So i believe what you're asking is: when should you handle an action with a saga, and when should you handle it with a reducer. The answer to that comes down to the reason redux-saga and similar middleware were created in the first place:
Reducers are always synchronous pure functions.
So you'll use a saga when you want to do something asynchronous and/or impure. The asynchronous part of that is the thing that comes up most often. If you want to fetch data, it will be in a saga. If you want to set up an interval to do something over time, it will be in a saga.
On rare occasions you might have something that's synchronous, but impure, and that might also be something you put in a saga. One recent example i had was that i wanted to dispatch an action, and rather than updating the application state, i wanted it to save something to local storage. This happens synchronously, but since it's a side effect it's better for me to put it in a saga.
As requested in the comments, a clarification about synchronous but impure. A function is synchronous if it does all its work before it returns. A function is pure if it 1) has no side effects and 2) for a given input, it always returns the same output.
A side effect is when a function changes something external to itself, but by a means other than its return value. With a pure function, i should be able to call it and assume that nothing has changed outside of that function. For example:
localStorage.setItem('data', 'hello world');
doSomething();
console.log(localStorage.getItem('data'));
If i know nothing about doSomething except that it's pure, then i can be certain that localStorage.getItem('data') will return 'hello world'. But on the other hand if doSomething is impure, then i can't make that assumption. In principle, the value in local storage could have been changed, resulting in a different log statement.
So a function that modifies local storage, such as the following, is impure despite being synchronous:
const doSomething = (value) => {
localStorage.setItem('data', value);
}
The second way something could be impure is if it doesn't always return the same thing for its same inputs. For example, the following function is synchronous but impure:
const getTime = () => {
return Date.now();
}
If i call that multiple times, i will usually get different numbers each time.
Both Redux Thunk and Redux Saga are middleware of Redux. What is the difference between two and how to determine when to use Redux Thunk or Redux Saga?
Both Redux Thunk and Redux Saga take care of dealing with side effects.
In very simple terms, applied to the most common scenario (async functions, specifically AJAX calls) Thunk allows Promises to deal with them, Saga uses Generators.
Thunk is simple to use and Promises are familiar to many developers, Saga/Generators are more powerful but you will need to learn them.
When Promises are just good enough, so is Thunk, when you deal with more complex cases on a regular basis, Saga gives you better tools.
As an example, what happens when you start an AJAX call in a route/view and then the user moves to a different one? Can you safely let the reducer change the state anyway? Saga makes it trivial to cancel the effect, Thunk requires you to take care of it, with solutions that don't scale as nicely.
In practical terms choosing one or the other one really depends (tautologically) on the project.
One thing to keep in mind is that the two middlewares can coexist, so you can start with Thunks and introduce Sagas when/if you need them (and then choose how/what to refactor with hands on experience... A solution that especially fits "learning projects", MVPs, et similia)
In general terms, Sagas are more powerful and easier to test, but they introduce many new concepts, that can be a bit overwhelming if you're also learning other technologies (Redux especially).
Specifically, while dealing with the simple and effective Redux philosophy (actions (literal objects) fed into reducers (pure functions)), you can deal with side effects with Thunk that is more limited but easy to grasp (Promise.then().error()), or with Saga that requires you to face the (powerful) notion that you can do more complex things with those actions.
It's also worth mentioning (redux-)observable has an even more complex (and even more powerful) paradigm to deal with side effects, just in case you are unfamiliar with it (if you already are, it might be easier to use than learning Saga).
Actually, Both of them are middleware for Redux to deal with asynchronous actions. For knowing the difference between then please pay attention to the following picture:
The middleware box generally refers to software services that glue together separate features in existing software. For Redux, middleware provides a third-party extension point between dispatching an action and handing the action off to the reducer. then reducer makes the new state.
Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store’s dispatch method, which is then used to dispatch regular synchronous actions inside the body of the function once the asynchronous operations have completed. simple, easy to learn and use with 352B volume
Redux Saga leverages an ES6 feature called Generators, allowing us to write asynchronous code that looks synchronous, and is very easy to test. In the saga, we can test our asynchronous flows easily and our actions stay pure. complicated, hard to learn and understand, 14kB volume but organized complicated asynchronous actions easily and make then very readable and the saga has many useful tools to deal with asynchronous actions
HINT: If you cannot understand the difference between them or understand the redux-saga flow but still you wanna have readable code and avoid callback hell, go after redux-thunk by using async/await, I leave an example for offer:
// simple usage of redux-thunk:
export const asyncApiCall = values => {
return dispatch => {
return axios.get(url)
.then(response =>{
dispatch(successHandle(response));
})
.catch(error => {
dispatch(errorHandle(error));
});
};
};
// async/await usage of redux-thunk:
export const asyncApiCall = values => {
return async dispatch => {
try {
const response = await axios.get(url);
dispatch(successHandle(response));
}
catch(error) {
dispatch(errorHandle(error));
}
};
};
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.