Javascript 如何将Formik字段组件抽象为通用共享组件

Javascript 如何将Formik字段组件抽象为通用共享组件,javascript,reactjs,formik,Javascript,Reactjs,Formik,我试图将formik组件抽象成一个单独的文件,这样我就可以在不同的表单中重用它,当我将组件分解成一个单独的文件并将其导入表单时,我遇到了一个错误(见下文)。在自定义组件中使用组件或passign可以正常工作,但导入它会引发错误。任何帮助都将不胜感激-克里斯 我尝试了多种方法(我的代码反映了哪些有效,哪些无效)。我已经翻遍了这些文档,在谷歌上搜索了很多,没有找到将组件抽象成单独文件的好例子 // Test-form.tsx import React from "react"; import { F

我试图将formik组件抽象成一个单独的文件,这样我就可以在不同的表单中重用它,当我将组件分解成一个单独的文件并将其导入表单时,我遇到了一个错误(见下文)。在自定义组件中使用组件或passign可以正常工作,但导入它会引发错误。任何帮助都将不胜感激-克里斯

我尝试了多种方法(我的代码反映了哪些有效,哪些无效)。我已经翻遍了这些文档,在谷歌上搜索了很多,没有找到将组件抽象成单独文件的好例子

// 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>
    </>
  );
};
//Test-form.tsx
从“React”导入React;
从“@cleaved/formik”导入{FormikTextField,CustomComponent};
从“Formik”导入{Form,Field,ErrorMessage,Formik,FormikActions};
类型TestFormProps={
地址:字符串;
名称:字符串;
电话:字符串;
};
导出常量TestForm=()=>{
返回(
{
动作。设置提交(错误);
}}
>
{({触摸,错误,提交})=>(
{/*1作品*/}
姓名:
{/*2工程*/}
{/*3不起作用*/}
{提交?“请稍候…”:“提交”}
)}
);
};
//formik-textbox.sx
从“React”导入React;
从“formik”导入{Field,FieldProps};
//2个作品
导出类型CustomComponentProps={
标签?:字符串;
名称:字符串;
占位符?:字符串;
键入:“文本”|“密码”;
};
导出常量自定义组件=({
标签,
名称
占位符,
类型,
表单:{toucted,errors},//还有值,setXXXX,handlexxx,dirty,isValid,status,等等。
…道具
}:any)=>(
{label}
{触摸[name]&&errors[name]&&{errors[name]}
);
//3不起作用
导出类型FormikTextFieldProps={
标签?:字符串;
名称:字符串;
占位符?:字符串;
键入:“文本”|“密码”;
};
export const FormikTextField:React.FC=({标签、名称、占位符、类型})=>(
{({field,form:{toucted,errors}}}:FieldProps)=>{
返回(
{label}
{触摸[name]&&errors[name]&&{errors[name]}
);
}}
);
导入组件(#3)时收到的错误消息如下:
未捕获类型错误:this.props.formik.registerField不是函数
在FieldInner.componentDidMount(formik.esm.js:811)
在提交周期(react dom.development.js:17334)
在提交生命周期(react dom.development.js:18736)
在htmlunknowneelement.callCallback(react dom.development.js:149)
在Object.invokeGuardedCallbackDev(react dom.development.js:199)
在invokeGuardedCallback(react dom.development.js:256)
在Commitrout(react dom.development.js:18948)
在react dom.development.js:20418
在Object.unstability\u runWithPriority(scheduler.development.js:255)
在completeRoot(react dom.development.js:20417)
在PerformWorkRoot(react dom.development.js:20346)
在performWork上(react dom.development.js:20254)
在performSyncWork(react dom.development.js:20228)
在requestWork(react dom.development.js:20097)
在scheduleWork(react dom.development.js:19911)
在scheduleRootUpdate上(react dom.development.js:20572)
在UpdateContainerExpirationTime(react dom.development.js:20600)
在updateContainer(react dom.development.js:20657)
在ReactRoot.dll_244e94d4223562f55cdd…/../../../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render(react-dom.development.js:20953)
在react dom.development.js:21090
在未分段更新时(react dom.development.js:20459)
在legacyRenderSubtreeIntoContainer(react dom.development.js:21086)
在Object.hydroge(react dom.development.js:21148)
在renderReactElement(index.js:31)
at_callee4$(index.js:35)
在tryCatch(runtime.js:45)
在Generator.invoke[as_invoke](runtime.js:271)
在发电机上。原型。[作为下一个](runtime.js:97)
在asyncGeneratorStep(asyncToGenerator.js:5)
at_next(asyncToGenerator.js:27)
在asyncToGenerator.js:34
在新的承诺()
在新的F(_export.js:36)
在asyncToGenerator.js:23
at_doRender(索引js:35)
在多伦德(索引:31)
at_callee2$(index.js:23)
在tryCatch(runtime.js:45)
在Generator.invoke[as_invoke](runtime.js:271)
在发电机上。原型。[作为下一个](runtime.js:97)
在asyncGeneratorStep(asyncToGenerator.js:5)
at_next(asyncToGenerator.js:27)
在asyncToGenerator.js:34
在新的承诺()
在新的F(_export.js:36)
在asyncToGenerator.js:23
at_render(index.js:23)
渲染时(index.js:20)
at_callee$(index.js:20)
在tryCatch(runtime.js:45)

toucted[name]&errors[name]
您正在将“address”作为名称传递,因此toucted或errors未定义。堆栈跟踪告诉您问题所在和正确的查找位置,不确定我们还可以添加什么。抱歉,我得到的真正错误是:Uncaught TypeError:this.props.formik.registerField不是函数。我更新了我的stacktrace。你正在使用所有功能组件,这个
来自哪里?我不知道。我的代码中没有引用“this”。我认为这与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)