如何将Formik Field组件抽象为通用可共享组件

时间:2019-09-13 21:46:08

标签: javascript reactjs formik

我正在尝试将formik组件提取到一个单独的文件中,所以当我将该组件分解到一个单独的文件并将其导入到一个文件中时,我可以以不同的形式重用它,并且遇到错误(请参阅下文)表格。使用组件或在自定义组件中使用passign都可以正常工作,但是导入它会引发错误。任何帮助,将不胜感激。 -克里斯

我尝试了多种方法(我的代码反映了什么有效,什么无效)。我已经浏览了文档,并在Google上搜索了很多,没有将组件抽象到单独文件中的好例子。

// Test-form.tsx
import React from "react";
import { FormikTextField, CustomComponent } from "@cleaved/formik";
import { Form, Field, ErrorMessage, Formik, FormikActions } from "formik";

type TestFormProps = {
  address: string;
  name: string;
  phone: string;
};

export const TestForm = () => {
  return (
    <>
      <Formik
        initialValues={{ address: "", name: "Chris Campbell", phone: "" }}
        onSubmit={(values: TestFormProps, actions: FormikActions<TestFormProps>) => {
          actions.setSubmitting(false);
        }}
      >
        {({ touched, errors, isSubmitting }) => (
          <Form>
            {/* 1 works */}
            <div className="form-group">
              <label htmlFor="name">Name: </label>
              <Field
                type="text"
                name="name"
                placeholder="name"
                className={`form-control ${touched.name && errors.name ? "is-invalid" : ""}`}
              />
              <ErrorMessage component="div" name="name" className="invalid-feedback" />
            </div>

            {/* 2 works */}
            <Field
              label="Phone: "
              name="phone"
              placeholder="enter phone number"
              type="text"
              component={CustomComponent}
            />

            {/* 3 doesn't work */}
            <FormikTextField label="address: " name="address" placeholder="enter address" type="text" />

            <button type="submit" className="btn btn-primary btn-block" disabled={isSubmitting}>
              {isSubmitting ? "Please wait..." : "Submit"}
            </button>
          </Form>
        )}
      </Formik>
    </>
  );
};
// formik-textbox.sx
import React from "react";
import { Field, FieldProps } from "formik";

// 2 works
export type CustomComponentProps = {
  label?: string;
  name: string;
  placeholder?: string;
  type: "text" | "password";
};

export const CustomComponent = ({
  label,
  name,
  placeholder,
  type,
  form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
  ...props
}: any) => (
  <div>
    <label>{label}</label>
    <input type={type} name={name} placeholder={placeholder} />
    {touched[name] && errors[name] && <div className="error">{errors[name]}</div>}
  </div>
);

// 3 doesn't work
export type FormikTextFieldProps = {
  label?: string;
  name: string;
  placeholder?: string;
  type: "text" | "password";
};

export const FormikTextField: React.FC<FormikTextFieldProps> = ({ label, name, placeholder, type }) => (
  <Field name={name}>
    {({ field, form: { touched, errors } }: FieldProps) => {
      return (
        <div>
          <label>{label}</label>
          <input type={type} name={name} placeholder={placeholder} />
          {touched[name] && errors[name] && <div className="error">{errors[name]}</div>}
        </div>
      );
    }}
  </Field>
);

The error message I'm receiving when importing the <Field /> component (#3) is below:

Uncaught TypeError: this.props.formik.registerField is not a function
    at FieldInner.componentDidMount (formik.esm.js:811)
    at commitLifeCycles (react-dom.development.js:17334)
    at commitAllLifeCycles (react-dom.development.js:18736)
    at HTMLUnknownElement.callCallback (react-dom.development.js:149)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:199)
    at invokeGuardedCallback (react-dom.development.js:256)
    at commitRoot (react-dom.development.js:18948)
    at react-dom.development.js:20418
    at Object.unstable_runWithPriority (scheduler.development.js:255)
    at completeRoot (react-dom.development.js:20417)
    at performWorkOnRoot (react-dom.development.js:20346)
    at performWork (react-dom.development.js:20254)
    at performSyncWork (react-dom.development.js:20228)
    at requestWork (react-dom.development.js:20097)
    at scheduleWork (react-dom.development.js:19911)
    at scheduleRootUpdate (react-dom.development.js:20572)
    at updateContainerAtExpirationTime (react-dom.development.js:20600)
    at updateContainer (react-dom.development.js:20657)
    at ReactRoot.dll_244e94d4223562f55cdd.../../../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render (react-dom.development.js:20953)
    at react-dom.development.js:21090
    at unbatchedUpdates (react-dom.development.js:20459)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:21086)
    at Object.hydrate (react-dom.development.js:21148)
    at renderReactElement (index.js:31)
    at _callee4$ (index.js:35)
    at tryCatch (runtime.js:45)
    at Generator.invoke [as _invoke] (runtime.js:271)
    at Generator.prototype.<computed> [as next] (runtime.js:97)
    at asyncGeneratorStep (asyncToGenerator.js:5)
    at _next (asyncToGenerator.js:27)
    at asyncToGenerator.js:34
    at new Promise (<anonymous>)
    at new F (_export.js:36)
    at asyncToGenerator.js:23
    at _doRender (index.js:35)
    at doRender (index.js:31)
    at _callee2$ (index.js:23)
    at tryCatch (runtime.js:45)
    at Generator.invoke [as _invoke] (runtime.js:271)
    at Generator.prototype.<computed> [as next] (runtime.js:97)
    at asyncGeneratorStep (asyncToGenerator.js:5)
    at _next (asyncToGenerator.js:27)
    at asyncToGenerator.js:34
    at new Promise (<anonymous>)
    at new F (_export.js:36)
    at asyncToGenerator.js:23
    at _render (index.js:23)
    at render (index.js:20)
    at _callee$ (index.js:20)
    at tryCatch (runtime.js:45)

0 个答案:

没有答案