How to run setSubmitting() outside the submit handler?

You could implement callbacks. Just invoke an onSuccess or onError callback in your middleware and handle them in your component.

// component.js
class LoginPage extends Component {

  // ...

  onSubmit = (values, { setSubmitting }) => {
    const { dispatch } = this.props

    setSubmitting(true);
    dispatch(
      login(
        values,
        () => setSubmitting(false), // success callback to be invoked in middleware
        (message) => { // error handler invoked in middleware catch
          this._handleErrorMessage(message);
          setSubmitting(false);
        },
      )
    );
  }


}

// actions.js
function loginAction(payload, onSuccess, onError) {
  return {
    type: LOGIN,
    payload,
    onSuccess,
    onError,
  }
}

// middleware.js
function handleLogin(action) {
  const { payload, onSuccess, onError } = action;
  try {
    // login...
    onSuccess('hurray!');
  } catch(error) {
    const { message } = error;
    onError(message);
  }
}

If the Formik component could accept isSubmitting as prop, then it could be implemented much more elegantly. Right now it doesn't (see source). This would be a great feature request to the Formik team.


Another approach is by using ref on to the <Formik/> component (released in React 16.3)

class NewComponent extends Component {
  formikRef = React.createRef()

  render() {
    <Formik
      ref={this.formikRef}
      ..
      ..
    />
  }

  onButtonClick() {
    this.formikRef.current.setSubmitting(false);
  }
}