web-dev-qa-db-fra.com

Comment exécuter setSubmitting () en dehors du gestionnaire de soumission?

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"?

12
Matheus Gomes

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);
  }
}
3
brettinternet

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.

1
ilonacodes

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);
  }
}
1
yashhy