2

I'm making input validations with formik, when my form is filled he calls the function handleSubmit, but this function is outside my hook component, so I can't call dispatchs.

How I can put the handleSubmit logic inside my hook component?

This is my code:

const schema = Yup.object().shape({
  email: Yup.string().email('Email don't have a valid format').required('Fill the email!'),
  password: Yup.string().required('Fill the password')
})

const enhanceWithFormik = withFormik({
  mapPropsToValues: () => 
  ({ 
      email: '', password: ''
  }),
  handleSubmit: values => {
    registerFirstData(values)
  },
  validateOnMount: false,
  validateOnChange: true,
  validateOnBlur: true,
  displayName: 'RegistrarForm',
  validationSchema: schema
})

const Register = props => {

const {
  values,
  touched,
  errors,
  isSubmitting,
  handleChange,
  handleBlur,
  handleSubmit
} = props;

return (
  <form onSubmit={handleSubmit} className={classes.form} noValidate>
   ...
  </form>
)
}

export default enhanceWithFormik(Register);

What i tried:

const Register = props => {

    const { enqueueSnackbar } = useSnackbar();

    const handleSubmit = values => {
      console.log(values)
    }

     const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        // Removed handleSubmit from here
    } = props;

    return (
         <Form onSubmit={handleSubmit} className={classes.form} noValidate>
    ...
    )

But this way my page is reloaded when i click in my submit button

bla
  • 995
  • 3
  • 11
  • 44

2 Answers2

3

How I can put the handleSubmit logic inside

It's very simple, don't use withFormik and use the Formik component.

const schema = Yup.object().shape({
    email: Yup.string().email('Email don\'t have a valid format').required('Fill the email!'),
    password: Yup.string().required('Fill the password')
})

const Register = props => {

    const onSubmit = values => {
        // Do what you want
        // Here you can call dispatch with the form values
        console.log(values)
    }

    return (
        <Formik
            initialValues={{
                email: '', password: ''
            }}
            validateOnMount={false}
            displayName='RegistrarForm'
            validationSchema={schema}
            onSubmit={onSubmit}
        >
            {({ values, touched, errors, isSubmitting, handleChange, handleBlur, handleSubmit }) => (
                <Form onSubmit={handleSubmit} className={classes.form} noValidate>
                    {/* ... */}
                </Form>
            )}
        </Formik>
    )
}

export default Register;
Vencovsky
  • 28,550
  • 17
  • 109
  • 176
1

I'm not entirely sure I understood your question correctly. Here's what I understood: You want to dispatch a Redux action when the form is submitted but can't do that, so you put a submit handler into the component (additionaly to the one in withFormik) and the result is that the page reloads on submit.

A couple things:

  • If you override the submit handler inside your component and pass that to the Form, the default implementation of Formik (which contains your submit handler from withFormik) does not apply any longer. Note that a submit handler takes an event (see https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onsubmit), not the values as you suggest in your custom submit handler inside the component. As you then do not call event.preventDefault() in your custom submit handler, the page is reloaded, as this is the default behavior for form submission.
  • Actually you should be able to dispatch a Redux action inside the withFormik definition. If you check out the Formik docs, handleSubmit is called with two parameters, values and actions. Next to the so called Formik helpers, actions contains the props of the enhanced component. Therefore, if you connect your component to the redux store and inside mapDispatchToProps pass in a prop like dispatchMyAction, you should be able to dispatch an action inside withFormik's handleSubmit function by calling actions.props.dispatchMyAction.

So I'd try something like this:

...

const enhanceWithFormik = withFormik({
  handleSubmit: (values, actions) => {
    registerFirstData(values)
    actions.props.dispatchMyAction()
  },
  ...
})

const Register = props => {
  return (
    <Form className={classes.form} noValidate>
      ...
    </Form>
  )
}

const mapDispatchToProps = dispatch => {
  return {
    dispatchMyAction: () => dispatch(myActionCreator())
  }
}

export default enhanceWithFormik(connect(null, mapDispatchToProps)(Register));

Of course I can't try if this solves your problem as you did't provide a MVE...

Michael H.
  • 3,323
  • 2
  • 23
  • 31