【问题标题】:How to run setSubmitting() outside the submit handler?如何在提交处理程序之外运行 setSubmitting()?
【发布时间】:2018-11-16 20:13:23
【问题描述】:

我正在尝试实现https://www.youtube.com/watch?v=5gl3cCB_26M 中描述的方法,其中所有 Redux 操作都只是普通对象(正如它们的本意那样),API 调用由中间件完成。

通过这样做,分派的操作不再是 thunk 并且不能返回 Promise。因此,我将无法在提交处理程序中使用 Formik 的 setSubmitting(将 isSubmitting 标志设置为 false),就像我发现的 Formik 文档和其他教程中的代码示例一样。

我以一种丑陋的方式解决了这个问题,保存了 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)

我怎样才能以更“优雅”的方式做到这一点?

【问题讨论】:

    标签: reactjs redux middleware formik


    【解决方案1】:

    另一种方法是在&lt;Formik/&gt; 组件上使用ref(在 React 16.3 中发布)

    class NewComponent extends Component {
      formikRef = React.createRef()
    
      render() {
        <Formik
          ref={this.formikRef}
          ..
          ..
        />
      }
    
      onButtonClick() {
        this.formikRef.current.setSubmitting(false);
      }
    }
    

    【讨论】:

    【解决方案2】:

    您可以实现回调。只需在中间件中调用 onSuccessonError 回调并在组件中处理它们。

    // 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);
      }
    }
    

    【讨论】:

    • 不错!只是做了一点调整,将回调放在 meta 属性中,以执行 FSA compliant 操作。
    • @MatheusGomes 不错!我喜欢这个主意。
    【解决方案3】:

    如果 Formik 组件可以接受isSubmitting 作为道具,那么它可以更优雅地实现。现在它没有(见source)。这对 Formik 团队来说是一个很好的功能要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 2016-08-28
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多