I'm trying to implement the approach described on https://www.youtube.com/watch?v=5gl3cCB_26M, where all Redux actions are just plain objects (as they were meant to be) and API calls are done by middlewares.
By doing this, the dispatched actions are no longer thunks and can't return a Promise
. So I won't be able to use Formik's setSubmitting
(to set the isSubmitting
flag to false
) inside the submit handler, like the code samples on Formik docs and other tutorials I've found.
I've solved the issue in a kinda ugly way, saving a reference of setSubmitting
to run it later, inside componentDidUpdate
:
import React, { Component } from 'react'
import { Redirect } from 'react-router-dom'
import LoginForm from 'path/to/LoginForm'
import validationSchema from 'path/to/LoginForm/validationSchema'
import { login } from 'path/to/actionCreators'
const initialValues = {
email: '',
password: '',
}
class LoginPage extends Component {
componentDidUpdate() {
const { auth } = this.props
if (!auth.isProcessing && this.setSubmitting) {
this.setSubmitting(false)
}
}
onSubmit = (values, { setSubmitting }) => {
const { dispatch } = this.props
dispatch(login(values)))
this.setSubmitting = setSubmitting
}
render() {
const { auth } = this.props
if (auth.user.uid) {
return <Redirect push to="/" />
}
return (
<div className="login-panel">
<h1>Login</h1>
<Formik
initialValues={initialValues}
onSubmit={this.onSubmit}
render={LoginForm}
validationSchema={validationSchema}
/>
</div>
)
}
}
const mapStateToProps = state => ({
auth: state.auth,
})
export default connect(mapStateToProps)(LoginPage)
How can I do it in a more "elegant" way ?
IMPORTANT: If onSubmit is async, then Formik will automatically set isSubmitting to false on your behalf once it has resolved. This means you do NOT need to call formikBag. setSubmitting(false) manually. However, if your onSubmit function is synchronous, then you need to call setSubmitting(false) on your own.
it is very simple just do console. log(formik. values) and you will get all the values without submitting it.
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);
}
}
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With