What happen if I have multiple middleware (lets say 3 for the exemple), all catching a single action ? Do they trigger in the order defined in the store creation ?
createStore(reducer,applyMiddleware(middle1, middle2, middle3));
middle1 will get triggered first, then middle2, then middle3 ? (when calling next() )
Can I on a specific action force middle3 to be called before middle2 ?
The middleware pipeline exactly matches the order that you passed to applyMiddleware(). So, in that example:
calling store.dispatch() passes the action to middle
when middle1 calls next(action), it goes to middle2
when middle2 calls next(action), it goes to middle3
when middle3 calls next(action), it goes to the actual store and the reducer logic is executed
And no, you cannot reorder middleware after the store has been created.
Related
I have a form which, when I submit, should call up 2 functions one by one and then run a condition that is dependent on the mentioned 2 functions.
The handler starts when you press the button, but how do you ensure that they will run sequentially and wait for the result of the previous one?
const handlerNextPage = () => {
controlValidInputs();
handlerSetValues();
inputsData.pages.isValid.page1 && navigate("step2");
};
Thank you
It depends from the nature of your functions and what you are doing inside of them.
If they execute all synchronous tasks, they will be called sequentially and will execute sequentially one after another, that's due to the synchronous single threaded nature of JavaScript engine Event Loop.
BUT
If inside one of those functions you are performing some asynchronous task, like an http fetch or a setTimout, the next function will be executed while the previous one async operations have not been performed yet. To handle those cases you need to use promises.
In your case I don't think you have any asynchronous task in your first function controlValidInputs() and in the second one I assume you are performing some React setState, the React setState is asynchronous but can't be handled with promises, you need to use the useEffect hook to defer operations after a react state update.
if they are synchronous functions so you don't need to worry about they will run one by one but if you are setting state which is asynchronous or calling API in the function which I see that's not the case here. But if you still call an API here in the function you can handle in quite easily by making the function into an async function and putting await but if you setstate and use it value right that is the tricky part because setState need little bit time before setting it so you need to update your logic little bit suppose handlerSetValues(); you setState in this function like this:
const handlerSetValues = () => {
// code here
// code here
// get value of state
setState(value) // this take little bit time so
return value // as well and use it handlerNextPage function
}
const handlerNextPage = () => {
controlValidInputs();
const value = handlerSetValues();
// now use value as state like you use below code I think.
inputsData.pages.isValid.page1 && navigate("step2");
};
you can useeffect
useEffect(()=>{
// inputsData.pages.isValid.page1 && navigate("step2");
},[depency-OnChanging-Which-Call-Code-Inside-Effect])
Im in React v16, Redux, saga 1.1.3, AWS cognito for UserMgmt
Requirements:
after creating a new user, email them a password reset link so they can log in and set their password
password reset action works perfectly
new user creation works perfectly
I need to call the pwd reset action once the new user is created. I'm targeting the saga as a good place to make this call. Once all the yields for the existing saga are done, right before setting state with put, i make one more yield call to the other action i want to run...and never see it do anything : )
is there a trick to running or dispatching actions from sagas.
this is the one line i need to run
cognitoActions.forgotPwd(email);
running it from my front end works every time.
also, it is imported
import { cognitoActions } from "fakepath/cognito";
on the front end mapping the action to props, passing it to the component, then calling it works every time...
just no action from the saga. i've tried logging results and dont think its running at all, no console.log happens...
You can use the "put" function to call it from within an effect like this:
yield put(action)
Potentially depending on what you want you can use:
putResolve(action)
You can find documentation for this here:
https://redux-saga.js.org/docs/api/
say the code below:
this.props.getRemoteUserId()
this.props.getRemotePrice()
the first function will get the userId and then with that Id I can fetch the new price. My question is : is this.props.getRemotePrice() fired after the new userId has save to the store?
That really depends on what is inside those functions. If they are both asynchronous AJAX calls for instance, then you can never be sure which one will finish first.
Now I check by using 'componentWillRecieveProps' to check 'nextProps' of Redux state is it finish or not.
like this example,
if (!nextProps.a.update && !nextProps.a.error &&
nextProps.a.update !== this.props.a.update) {
const oldData = [...this.props.a.data];
const newData = [...nextProps.a.data];
.
.
.
});
}
}
Did anyone have another good idea to check it?
Thanks.
if you are using any middleware like Redux-saga or thunk you can check whether update is done or not from the middleware itself and once its updated you can dispatch an action from middleware itself and get notified.
Not sure how much it will be appropriate for your case.
It really depends.
1. If the logic your'e trying to implement, is only for same component, and from one dispatched action only at a time, then using a flag is definitely OK, set true on 'will update' and false on 'did update' (same for mount if necessary).
2. If the logic is upon few actions, then maybe create a bulking mechanism using promise will be better. Again, depends on your logic. Maybe it will be enough to use flags for each type of update.
3. If the logic is system wide, i would use a global variable, maybe even set on 'window'. For example, i wanted to implement a variable called 'isLoading', which will define if there's any pending ajax call.
Please let me know if that's what you've been looking for.
In my React application i'm using Long-polling API. In order to automatically send requests on every response i use middleware. But before sending new request, i have to save received data in store. More than that, i want to dispatch another action inside my middleware. So my structure looks like this:
InitLongPoll() -> SendRequest(data) -> ReceiveResponse(data)* -> SendRequest(data)
'*' is my middleware. From there i'm saving data to the store using store.dispatch(responseData) and sending new request using store.dispatch(sendRequest(authData)).
Is it okay to receive that authData using store.getState().authReducer? As far as i know, my middleware should be a pure function and shouldn't depend on external data (store). Thanks in advance.
Is it okay to receive that authData using
store.getState().authReducer? As far as i know, my middleware should
be a pure function and shouldn't depend on external data (store).
Yes it is. Middleware is the way to introduce side effects into the redux loop, and it can't be a pure function. Your own middleware has a side effect - polling the server.
A redux middleware is the anti-thesis of a pure function, which is defined as:
The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any
hidden information or state that may change while program execution
proceeds or between different executions of the program, nor can it
depend on any external input from I/O devices (usually—see below).
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output
to I/O devices (usually—see below).
You can also see in the redux-thunk source code, that it uses getState:
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}