javascript - Formik dispatch Redux action after valid field change - Stack Overflow

admin2025-04-19  0

I've built this sandbox React application that uses Formik forms.

I want to dispatch a Redux action if the email field validation fires and is valid. I want to dispatch the action to do some lookup from the users email. This action will update redux state and populate some other field on my form.

So this dispatch would happen if the email field was valid. The other fields could be invalid and I haven't submitted the form yet.

How do I do that? I can't find any documentation on this!

Thanks!

I've built this sandbox React application that uses Formik forms.

I want to dispatch a Redux action if the email field validation fires and is valid. I want to dispatch the action to do some lookup from the users email. This action will update redux state and populate some other field on my form.

So this dispatch would happen if the email field was valid. The other fields could be invalid and I haven't submitted the form yet.

How do I do that? I can't find any documentation on this!

https://codesandbox.io/s/x32yoo242q

Thanks!

Share Improve this question edited Apr 14, 2019 at 20:49 etarhan 4,1762 gold badges17 silver badges29 bronze badges asked Apr 14, 2019 at 17:46 HiddenHidden 7,5025 gold badges48 silver badges55 bronze badges 3
  • 1 Not sure I understand the question... You'd set up redux and then call an action creator from the handleSubmit instead of just alerting... Seems your sandbox doesn't have redux set up at all... – SakoBu Commented Apr 14, 2019 at 18:39
  • Sorry - i mean id like to fire the action when the individual field has changed and is valid. Rather when the entire form is pleted and valid. – Hidden Commented Apr 14, 2019 at 19:23
  • Ok, I think I understand... in the sandbox name is missing from the input which is how Formik identifies the fields and much more.... You’d get a lot more value out of this 40 min vid than a paragraph here... here you go: youtu.be/yNiJkjEwmpw – SakoBu Commented Apr 14, 2019 at 19:41
Add a ment  | 

2 Answers 2

Reset to default 3

You can create a reusable custom ponent that calls a secondary action on input updates. In this case, it'll dispatch an action (redux action) if the input is valid and has a value, and/or optionally dispatch a secondary action if invalid.

Update: Utilize ponentDidUpdate. It's less verbose and requires less manual field level handling. In addition, you should also debounce the function to avoid a lot of redux action triggers.

Working example (email):

Working example (Material UI Select):


ponents/Input (custom ponent -- ponentDidUpdate controls whether or not to call validateField)

import React, { Fragment, PureComponent } from "react";

class Input extends PureComponent {
  ponentDidUpdate = prevProps => {
    const { errors, value } = this.props;
    if (errors !== prevProps.errors || value !== prevProps.value) {
      this.props.validateField({ errors, value });
    }
  };

  render = () => {
    const { errors, label, name, touched, validateField, ...rest } = this.props;
    return (
      <Fragment>
        <label htmlFor={name} style={{ display: "block" }}>
          {label}
        </label>
        <input {...rest} name={name} />
        {errors && touched && (
          <div style={{ color: "red", marginTop: ".5rem" }}>{errors}</div>
        )}
      </Fragment>
    );
  };
}

export default Input;

containers/Form (validateField controls the redux action)

import debounce from "lodash/debounce";
import React from "react";
import { withFormik } from "formik";
import Input from "../../ponents/Input";
import DisplayFormikState from "../../ponents/DisplayFormState";
import { resetMessage, setMessage } from "../../actions/message";
import store from "../../store";
import * as Yup from "yup";

const formikEnhancer = withFormik({
  validationSchema: Yup.object().shape({
    email: Yup.string()
      .email("Invalid email address")
      .required("Email is required!")
  }),
  mapPropsToValues: props => ({
    email: ""
  }),
  handleSubmit: (values, { setSubmitting }) => {
    const payload = {
      ...values
    };

    setTimeout(() => {
      alert(JSON.stringify(payload, null, 2));
      setSubmitting(false);
    }, 1000);
  },
  displayName: "MyForm"
});

const handleFormReset = handleReset => {
  store.dispatch(resetMessage());
  handleReset();
};

const validateField = debounce(
  ({ errors, value }) =>
    !errors && value
      ? store.dispatch(setMessage())
      : store.dispatch(resetMessage()),
  500
);

const MyForm = props => {
  const {
    values,
    touched,
    dirty,
    errors,
    handleBlur,
    handleChange,
    handleReset,
    handleSubmit,
    isSubmitting
  } = props;

  return (
    <form onSubmit={handleSubmit}>
      <Input
        name="email"
        label="Email"
        type="email"
        placeholder="Enter an email address."
        errors={errors.email}
        value={values.email}
        touched={touched.email}
        onChange={handleChange}
        onBlur={handleBlur}
        validateField={validateField}
      />
      <button
        type="button"
        className="outline"
        onClick={() => handleFormReset(handleReset)}
        disabled={!dirty || isSubmitting}
      >
        Reset
      </button>
      <button type="submit" disabled={isSubmitting}>
        Submit
      </button>

      <DisplayFormikState {...props} />
    </form>
  );
};

export default formikEnhancer(MyForm);

The easiest and most straightforward way to achieve what you want is by using the onBlur handler of your email input. You can extend the default handler by doing the following:

<input
  id="email"
  placeholder="Enter your email"
  type="email"
  value={values.email}
  onChange={handleChange}
  onBlur={e => {
    handleBlur(e);
    if (!errors.email) {
      console.log("dispatch: ", e.currentTarget.value);
    }
  }}
/>

By also calling the Formik's handleBlur first you keep the default validation behavior, while also adding your own afterwards. Your form is validating onChange as well as onBlur so errors.email should always give an accurate representation of validity for the email input, which we can use to dispatch if the email is valid on blur (In my example I'm just logging something to the console to illustrate). Check out the sandbox to see it in action:

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745003371a279365.html

最新回复(0)