mhssmnn/redux-form-saga

Redux Form Submission Errors

Closed this issue · 8 comments

What's the recommended way to use redux-form submission errors with redux-form-saga?

Normally, if the promise passed to handleSubmit rejects, redux form will extract errors from the rejected object, where each key corresponds to a field (Scroll to onSubmit). Alternatively, the key _error can be used to specify a form wide error. The way I see it in formActionSaga, the promise will always reject with the full failure action passed to createFormAction, e.g. { type: 'FAILURE', payload: 'Error: something wrong happened', error: true }, so redux-form will never receive a compatible error object. Below is an example of what would work although it's not an actual suggestion for a fix. Just wanted to know how you guys approached that problem.

function *formActionSaga () {
    // ...

    const winner = yield race({
      success: take(SUCCESS),
      fail: take(FAIL)
    });

    if (winner.success) {
      yield call(resolve, winner.success);
    } else {
      yield call(reject, winner.fail.payload); // this would work if payload had the form { _error: 'This form has an error' } for example
    }
  }
}
cj commented

I'm having the same issue trying to display form errors.

@cj I ended up using reduxForm's returnRejectedSubmitPromise option in the constructor and passing the error messages by manually dispatching reduxForm's error action. For example:

// in actions.js

export const MY_FORM_REQUEST = 'MY_FORM_REQUEST';
export const MY_FORM_SUCCESS = 'MY_FORM_SUCCESS';
export const MY_FORM_FAILURE = 'MY_FORM_FAILURE';

export const myFormRequestAction = createAction(MY_FORM_REQUEST);
export const myFormSuccessAction = createAction(MY_FORM_SUCCESS);
export const myFormFailureAction = createAction(MY_FORM_FAILURE);

export const myFormActions = createFormAction(myFormRequestAction, [MY_FORM_SUCCESS, MY_FORM_FAILURE]);
// In form component 

import {myFormActions} from './actions';

class myForm extends React.Component {
  constructor(props) {
      super(props);
      // ....
      this.onSubmit = this.onSubmit.bind(this);
   }

  onSubmit(e) {
        const { handleSubmit, dispatch, resetForm } = this.props;

        handleSubmit(myFormActions)(e)
            .then(action => {
                resetForm();
                // Do success actions here
            })
            .catch(err => {
                dispatch({
                    type: 'redux-form/STOP_SUBMIT',
                    errors: err.payload,
                    form: 'myform'
                })
            })
  }
  render() {
     <form onSubmit={this.onSubmit}>
          // ...
     </form>
  }
}

myForm = reduxForm({
    form: 'myform',
    fields: ['id', 'name', 'description'],
    returnRejectedSubmitPromise: true
})(myForm);
// in saga 

function* watchMyForm() {
    while (true) {
        let action = yield take(MY_FORM_REQUEST);
        try {
            // do something
            yield put(suggestionFormSuccessAction());
        } catch (err) {
            // build error messages
            yield put(suggestionFormFailureAction({ _error: err.message }));
        }
    }
}

It's not entirely clean but it works. Looking forward to other suggestions on how to best handle this!

Better yet, have a look at this thread: redux-saga/redux-saga#161

FYI: I forked this repo, fixed this problem as well as made a cleanup (code and dependencies) and published a new package to NPM, you can find it here: https://www.npmjs.com/package/redux-saga-actions.

@mhssmnn, sorry, but we need all these fixes in production asap and we can't wait so long for you to merge all pull requests.

Fair call @afitiskin – I'm travelling at the moment so haven't had consistent time to look at this. If you'd like to become a contributor on this repo, let me know.

Also, I'm sure there's a more generic abstraction here, which redux-saga-actions may become, which handles request, success, fail scenarios.

Anyway, I've merged #11 for now and published to NPM.

@mhssmnn I have some Ideas about new features, that will be included in the redux-saga-actions package and will simplify not just Redux Form submit handling but many other API interaction cases. Within redux-form-saga implementing of these features is not correct, so as I see the most proper variant is to have a new package based on redux-form-saga.

About participating as contributor: with pleasure will join the project.

@afitiskin I don't see any other functionality at redux-aga-actions which is not at redux-form-saga. These some ideas in only in your mind yet? :-)

@sergeyzwezdin yep, will implement it soon :)