https://www.youtube.com/watch?v=5gl3cCB_26M に記載されているアプローチを実装しようとしています。ここで、すべてのReduxアクションは単なるオブジェクト(本来の目的)であり、 API呼び出しはミドルウェアによって行われます。
これにより、ディスパッチされたアクションはサンクではなくなり、Promise
を返すことができなくなります。そのため、Formikのドキュメントやその他のチュートリアルのコードサンプルのように、送信ハンドラ内でFormikのsetSubmitting
(isSubmitting
フラグをfalse
に設定するため)を使用できません。見つけた。
私は少し醜い方法で問題を解決しました、setSubmitting
内で後で実行するために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)
より「エレガント」な方法でそれを行うにはどうすればよいですか?
コールバックを実装できます。ミドルウェアでonSuccess
またはonError
コールバックを呼び出し、コンポーネントで処理するだけです。
// 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);
}
}
FormikコンポーネントがisSubmitting
をpropとして受け入れることができれば、よりエレガントに実装できます。現時点ではサポートされていません( source を参照)。これは、Formikチームへの優れた機能リクエストです。
別のアプローチは、<Formik/>
コンポーネントに= ref を使用することです(React 16.3でリリース)
class NewComponent extends Component {
formikRef = React.createRef()
render() {
<Formik
ref={this.formikRef}
..
..
/>
}
onButtonClick() {
this.formikRef.current.setSubmitting(false);
}
}