web-dev-qa-db-ja.com

送信ハンドラの外でsetSubmitting()を実行するにはどうすればよいですか?

https://www.youtube.com/watch?v=5gl3cCB_26M に記載されているアプローチを実装しようとしています。ここで、すべてのReduxアクションは単なるオブジェクト(本来の目的)であり、 API呼び出しはミドルウェアによって行われます。

これにより、ディスパッチされたアクションはサンクではなくなり、Promiseを返すことができなくなります。そのため、Formikのドキュメントやその他のチュートリアルのコードサンプルのように、送信ハンドラ内でFormikのsetSubmittingisSubmittingフラグを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)

より「エレガント」な方法でそれを行うにはどうすればよいですか?

12
Matheus Gomes

コールバックを実装できます。ミドルウェアで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);
  }
}
3
brettinternet

FormikコンポーネントがisSubmittingをpropとして受け入れることができれば、よりエレガントに実装できます。現時点ではサポートされていません( source を参照)。これは、Formikチームへの優れた機能リクエストです。

1
ilonacodes

別のアプローチは、<Formik/>コンポーネントに= ref を使用することです(React 16.3でリリース)

class NewComponent extends Component {
  formikRef = React.createRef()

  render() {
    <Formik
      ref={this.formikRef}
      ..
      ..
    />
  }

  onButtonClick() {
    this.formikRef.current.setSubmitting(false);
  }
}
1
yashhy