New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: Async validation with redux-saga #655
Comments
Hmm... I've been watching |
I'm quite a beginner when it comes to the whole redux scene but the idea I'm struggling with is the concept of an action having a return value. I'm pretty sure this is what redux-form expects when I call an action on submit, but I don't think I'm able to implement this with a saga. If it helps at all this is what my saga looks like, should be pretty easy to tell what it does; function* sendRequest(token) {
while (true) {
//Wait for an API call
const callAPI = yield take(action => action.CALL_API);
let { endpoint, data } = callAPI;
const { types } = callAPI;
const [ requestType, successType, failureType ] = types;
//Dispatch the request_started action
yield put(formatAPIActionToDefaultAction({ type: requestType }));
//Dispatch action to display loader
yield put(displayLoader());
const response = yield call(callApi, endpoint, data, token);
//Response is done, hide loader
yield put(hideLoader());
if(response.hasOwnProperty("error")) {
//Request failed
yield put(formatAPIActionToDefaultAction({ type: failureType }));
yield parseAPIError(response.type, response.error);
//This sets either validationErrors or generalError on my state
//Check for a failure route
if (callAPI => callAPI.failureRoute) {
Actions[callAPI.failureRoute](); //Call it
}
} else {
//Request success!
yield put(formatAPIActionToDefaultAction({ type: successType, response: response.json }));
//Check for a success route
if (callAPI => callAPI.successRoute) {
Actions[callAPI.successRoute](); //Call it
}
}
//Set token for next request
//If token expired it will now be false, this will trigger a redirect to
//login
yield put(setToken(response.token));
}
} |
I have been working with that, and my solution is to disable (monkey patch) the automatic dispatch of stop_submit. |
Uh, sorry, did not mentioned the validation. I manually do it in the saga, and handle the submit. |
@mattiamanzati Makes sense, thanks for the push in the right direction! |
@erikras Should we consider about adding a behaviour where if onSubmit is not defined redux-form will only dispatch the START_SUBMIT action? |
@mattiamanzati Hmm... I'm not sure. As it is, it will only dispatch the |
Uhm... I don't know, I personally love to listen to redux-form's action, but tbh let the user manually dispatch it's own submit action and listen to that maybe it's better on long life application, as you could change the underlaying form package with almost no changes. |
Could you provide an example of how you did this? |
You can manually dispatch import { stopSubmit } from 'redux-form';
// ...
try {
const response = yield apiCall();
// ...
} catch (response) {
const errors = ...;
yield put(stopSubmit('FORM_NAME', errors));
} |
@erikras I agree with @mattiamanzati
onSubmit: (...) => {
setTimeout(() => {
// Dispatch action;
});
// Returns never resolved promise...
return new Promise(() => { / *Later dispatch stopSubmit from a saga. */ });
} With redux-saga we need a way to force redux-form only dispatch the onSubmit: (...) => {
// Dispatch action... Later dispatch stopSubmit from a saga.
return START_ASYNC;
} https://github.com/erikras/redux-form/blob/master/src/handleSubmit.js#L11 |
Or even better: onSubmit: (...) => {
// Dispatch action... Dispatch startSubmit/stopSubmit from a saga.
return ON_SUBMIT; // { type: "redux-form/ON_SUBMIT", form: "form"} }
} |
I'm using @mohebifar's solution (which works very well) but it does cause |
@Anahkiasen I don't remember all the details, but take a look at this solution redux-saga/redux-saga#161 (comment) |
@rosendi Worked like a charm, thanks! |
I don't want to involve promises at all (cause microtasks can bite you in the ass depending on how you use redux-saga). Also, I don't want functions ( [Edit] |
Any progress on finding out a better solution for this one, anyone? Returning a promise which never resolves seems a bit hacky and memory-leaky to me. On the other hand, handling all the async validation business myself using start/stop async validation is possible and very flexible, but it feels like I would have to reimplement a lot of the current behavior myself - inevitably introducing bugs in the process. So is the unresolved promise maybe the best way after all? Agreed with @Alxandr that having the ability to opt out of using promises at all would probably be the best solution. |
I went with quite different way of solving this - instead of dispatching any API_REQUEST-like action, I am dispatching |
Suggesting this get's added to the documentation along with #3235. |
Because this issue saw almost no activity for a few months, I'm closing it. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I've been stuck trying to think this out for a while now.
I have a saga that catches API_REQUEST actions, that in turn executes the request and sets
validationErrors
on my state if there are any. How can I invalidate a redux-form with this data?The text was updated successfully, but these errors were encountered: