J'essaie d'implémenter l'approche décrite sur https://www.youtube.com/watch?v=5gl3cCB_26M , où toutes les actions Redux ne sont que des objets simples (comme elles étaient censées l'être) et Les appels d'API sont effectués par des middlewares.
En faisant cela, les actions distribuées ne sont plus des thunks et ne peuvent pas retourner un Promise
. Je ne pourrai donc pas utiliser setSubmitting
de Formik (pour définir l'indicateur isSubmitting
sur false
) dans le gestionnaire de soumission, comme les exemples de code sur les documents Formik et d'autres didacticiels J'ai trouvé.
J'ai résolu le problème de manière un peu laide, en enregistrant une référence de setSubmitting
pour l'exécuter plus tard, dans 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)
Comment puis-je le faire de manière plus "élégante"?
Vous pouvez implémenter des rappels. Appelez simplement un rappel onSuccess
ou onError
dans votre middleware et gérez-les dans votre composant.
// 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);
}
}
Si le composant Formik pouvait accepter isSubmitting
comme accessoire, alors il pourrait être implémenté beaucoup plus élégamment. Pour l'instant, ce n'est pas le cas (voir source ). Ce serait une excellente demande de fonctionnalité pour l'équipe Formik.
Une autre approche consiste à utiliser ref sur le <Formik/>
composant (publié dans React 16.3)
class NewComponent extends Component {
formikRef = React.createRef()
render() {
<Formik
ref={this.formikRef}
..
..
/>
}
onButtonClick() {
this.formikRef.current.setSubmitting(false);
}
}