reactjsreduxreact-reduxredux-formredux-thunk

Manually set redux-form field and/or form errors


I'm aware that if you throw a SubmissionError from your handleSubmit() function, the redux-form code will fill in the errors of the appropriate fields and/or the form itself.

Yet that API of setting field/form errors, tightly couples our implementation of handleSumbit() to be a caller of the redux-form code (which contains the SubmissionError exception handler).

My use case is to have something like so:

function asyncActionDispatcher(values) {                                     
  return (dispatch, getState) => {                                           
    // I'm using getState, which is not accessible in handleSubmit()         
    // But I'd also like to be able to set errors on the form fields and/or the
    // form.                                                                 
  };                                                                         
}                                                                            

function handleSubmit(values, dispatch) {                                    
  dispatch(                                                                  
    asyncActionDispatcher(values)                                            
  );                                                                         
} 

I can't throw a SubmissionError in asyncActionDispatcher() because it's called by redux and not redux-form.

Does redux-form have another API to set errors on fields/form?


Solution

  • Yes, it does.

    You can use validate and asyncValidate props to set validator functions for the values of your form (synchronous and asynchronous respectively).

    validate should be a function that either returns an empty object if validations pass or an object detailing validation errors in the form { someField: 'some error', otherField: 'other error' }

    asyncValidate on the other hand should return a Promise that is resolved normally if validations pass or that is rejected with an object detailing validation errors (see above) if validations do not pass.

    handleSubmit is implemented in such a way that it runs both synchronous and asynchronous validations before calling onSubmit, so if you've set up validate and asyncValidate, those errors should appear in your form/fields automatically without any additional work.

    Hope this helps!

    Update:

    You could also just wait until asyncActionDispatcher finishes and continue submitting or reject with a SubmissionError depending on what the results from it were.

    function asyncActionDispatcher(values) {
      return (dispatch, getState) => {
        if (success) {
          return Promise.resolve('success')
        } else {
          return Promise.reject('error')
        }
      }
    }
    
    function onSubmit(values, dispatch) {
      // dispatch whatever action you need to dispatch
      return dispatch(asyncActionDispatcher(values))
        .then(() => {
          // i guess you need to do your actual submitting here
        })
        .catch(error => {
          return new SubmissionError({ _error: 'whatever you want here' })
        })
    }
    
    // and in the component
    <form onSubmit={ handleSubmit(onSubmit) }> ... </form>
    

    Sources: Redux-Form docs, wrapped component props documentation, synchronous validation example, asynchronous validation example