有效字段更改后,Formik将分派Redux操作

时间:2019-04-14 17:46:43

标签: javascript reactjs redux formik

我已经构建了使用Formik表单的沙盒React应用程序。

如果电子邮件字段验证已触发并且有效,我想调度Redux操作。 我想调度该操作以从用户电子邮件中进行一些查找。此操作将更新redux状态并填充表单上的其他字段。

因此,如果电子邮件字段有效,则将发生此调度。其他字段可能无效,我尚未提交表格。

我该怎么做?我找不到任何文档!

https://codesandbox.io/s/x32yoo242q

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以创建可重用的自定义component,以对input更新进行次要操作。在这种情况下,如果输入有效且具有值,它将分派action(redux操作),和/或如果无效则分派次要操作。

更新:使用componentDidUpdate。它不那么冗长,并且需要较少的手动字段级别处理。另外,您还应该debounce使用该函数来避免大量的redux操作触发器。

工作示例(电子邮件)

Edit Formik Redux Yup Example

工作示例(材料UI选择)

Edit Formik Redux Yup MaterialUI


组件/输入(自定义组件-componentDidUpdate控制是否调用validateField

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

class Input extends PureComponent {
  componentDidUpdate = 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;

容器/表单validateField控制还原操作)

import debounce from "lodash/debounce";
import React from "react";
import { withFormik } from "formik";
import Input from "../../components/Input";
import DisplayFormikState from "../../components/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);

答案 1 :(得分:1)

使用电子邮件输入的 onBlur 处理程序,最简单,最直接的方法即可实现所需的目标。您可以通过执行以下操作来扩展默认处理程序:

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

首先还要调用Formik的 handleBlur ,然后保留默认的验证行为,然后再添加自己的验证行为。您的表格正在验证 onChange onBlur ,因此 errors.email 应该始终准确地表示电子邮件输入的有效性,如果电子邮件在模糊时有效,我们可以使用它来调度(在我的示例中,我只是在控制台上记录了一些内容以进行说明)。检出沙盒以查看其运行情况:

Edit Formik 1.2 x React Select Example