如何在提交处理程序之外 运行 setSubmitting()?
How to run setSubmitting() outside the submit handler?
我正在尝试实现 https://www.youtube.com/watch?v=5gl3cCB_26M 中描述的方法,其中所有 Redux 操作都只是普通对象(因为它们本来就是)并且 API 调用由中间件完成。
通过这样做,分派的动作不再是 thunk 并且不能 return Promise
。所以我将无法在提交处理程序中使用 Formik 的 setSubmitting
(将 isSubmitting
标志设置为 false
),就像 Formik 文档和其他教程中的代码示例一样找到了。
我已经以一种有点丑陋的方式解决了这个问题,稍后在 componentDidUpdate
:
中将 setSubmitting
的引用保存到 运行
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)
我怎样才能以更 "elegant" 的方式做到这一点?
如果 Formik 组件可以接受 isSubmitting
作为 prop,那么它可以更优雅地实现。现在它没有(参见 source)。这对 Formik 团队来说是一个很棒的功能请求。
您可以实现回调。只需在您的中间件中调用 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/>
组件上使用 ref (在 React 16.3 中发布)
class NewComponent extends Component {
formikRef = React.createRef()
render() {
<Formik
ref={this.formikRef}
..
..
/>
}
onButtonClick() {
this.formikRef.current.setSubmitting(false);
}
}
我正在尝试实现 https://www.youtube.com/watch?v=5gl3cCB_26M 中描述的方法,其中所有 Redux 操作都只是普通对象(因为它们本来就是)并且 API 调用由中间件完成。
通过这样做,分派的动作不再是 thunk 并且不能 return Promise
。所以我将无法在提交处理程序中使用 Formik 的 setSubmitting
(将 isSubmitting
标志设置为 false
),就像 Formik 文档和其他教程中的代码示例一样找到了。
我已经以一种有点丑陋的方式解决了这个问题,稍后在 componentDidUpdate
:
setSubmitting
的引用保存到 运行
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)
我怎样才能以更 "elegant" 的方式做到这一点?
如果 Formik 组件可以接受 isSubmitting
作为 prop,那么它可以更优雅地实现。现在它没有(参见 source)。这对 Formik 团队来说是一个很棒的功能请求。
您可以实现回调。只需在您的中间件中调用 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/>
组件上使用 ref (在 React 16.3 中发布)
class NewComponent extends Component {
formikRef = React.createRef()
render() {
<Formik
ref={this.formikRef}
..
..
/>
}
onButtonClick() {
this.formikRef.current.setSubmitting(false);
}
}