反应|如何将FormikProps传递给一个组件 [英] React | How to Pass FormikProps one Component Up

查看:74
本文介绍了反应|如何将FormikProps传递给一个组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试传递valuesprops,该formik需要1个组件.我将各种小组件用于某些形式,并将它们传递到一个复杂的组件中,该组件需要在调用时传递给每个单独的渲染器.

I am trying to pass values and props, that formik needs 1 component up. I am using various little components for some forms, and I am passing them in a complex component that needs to pass them down to each individual render when called.

基本上所有FormikProps.这是一个这样的组件.

Basically all the FormikProps. Here is one such component.

import React, { Fragment } from 'react';
import debounce from 'debounce-promise';
import classNames from 'classnames';
import { Field, FormikProps, ErrorMessage } from 'formik';

import Asterisk from 'shared/common/components/element/Asterisk';
import { validateUsername } from '../../utils/index';

interface IValues {
  username?: string;
  email?: string;
}

export const InfoFields = (props: FormikProps<IValues>): JSX.Element => {
  const debounceUsernameValidation = (): void => {
    debounce(validateUsername, 500);
  };

  const { touched, errors } = props;

  return (
    <Fragment>
      <div className="pb-2">
        <label className="font-weight-bold" htmlFor="username">
          Username <Asterisk />
        </label>
        <Field
          validate={debounceUsernameValidation}
          className={classNames('form-control', {
            'is-invalid': errors.username && touched.username
          })}
          placeholder="Username (Required)"
          autoComplete="username"
          name="username"
          type="text"
        />
        <ErrorMessage name="username" component="div" className="text-danger" />
      </div>
      <div className="py-2">
        <label className="font-weight-bold">Email</label>
        <Field
          className={classNames('form-control', {
            'is-invalid': errors.email && touched.email
          })}
          autoComplete="email"
          placeholder="Email"
          name="email"
          type="email"
        />
        <ErrorMessage name="email" component="div" className="text-danger" />
      </div>
    </Fragment>
  );
};

export default InfoFields;

在这里,我在复杂的组件内部调用它:

And here I am calling it inside the complex component:



  render(): ReactNode {
    const { mode } = this.props;
    return (
      <Formik
        initialValues={this.getInitialValues()}
        validationSchema={this.getValidationSchemas()}
        onSubmit={this.handleSubmit}
        validateOnBlur={false}
        render={({ status, isSubmitting }) =>
          (
            <Form>
              {status && (
                <div className="mb-3 text-danger" data-test="user-form-error-message">
                  {status}
                </div>
              )}
              {mode === ActionMode.ADD_USER && (
                <Fragment>
                  <InfoFields /> // This is the component from above
                </Fragment>
              )}
              <Button
                className="btn btn-primary w-100 mt-5"
                disabled={isSubmitting}
                loading={isSubmitting}
                type="submit"
              >
                {mode === ActionMode.ADD_USER && <span>CREATE USER</span>}
              </Button>
            </Form>
          ) as ReactNode
        }
      />
    );
  }

现在,当我在另一个组件中调用该组件时,会出现此错误:

Now when I call that component inside another one, I get this error:

Uncaught TypeError: Cannot read property 'username' of undefined. It refers to this line of code:
errors.username && touched.username and this
errors.email && touched.email

interface IProps {
  doSubmit(service: object, values: object): LensesHttpResponse<string>;
  onSave(values: { username?: string; email?: string; password?: string; group?: string }): void;
  notify(config: object): void;
  mode: ActionMode;
  user: IUser;
}

interface IValues extends FormikValues {
  username?: string;
  email?: string;
  password?: string;
  group?: string;
}

我需要一种将道具username, email和其余道具传递给每个单独组件的方法.问题在于该组件被称为2渲染,因此它无法访问

I need a way to pass the props username, email and the rest to each individual compoenent.The problem is the component is called 2 renders down, so it doesn't have access to them

我真是不知所措.有人能帮我吗?谢谢!

I am kind at a loss here. Can someone help me? Thanks!!

推荐答案

尽管您已经编写了接受FormikProps<IValues>的组件,但实际上并没有将道具传递给InfoFields.您可以像这样传递Formik的道具:

You aren't actually passing props to InfoFields although you've written that component to accept FormikProps<IValues>. Either you can pass Formik's props in like this:

<Formik
    render={formikProps => (
        <Form>
            // Other Code.

            <InfoFields {...formikProps} />

            // Other Code.
        </Form>
    )}
/>

或者(根据我的个人喜好),删除InfoField的道具并将Field用作渲染道具,例如:

Or (my personal preference), remove InfoField's props and use Field as a render prop, for example:

<Field
    name="username"
    validate={debounceUsernameValidation}
>
    {({ field, form }: FieldProps) => (
        <Fragment>
            <input
                {...field}
                className={classNames('form-control', {
                    'is-invalid': form.errors[field.name] &&
                        form.touched[field.name]
                })}
                placeholder="Username (Required)"
                type="text"
            />
            <ErrorMessage 
                name={field.name} 
                component="div" 
                className="text-danger" 
            />
        </Fragment>
    )}
</Field>

使用字段渲染道具,您可以访问嵌套在更下方的组件中的表单值,而无需在整个地方传递道具.

With the field render prop you can access the form values in components nested further down without passing props all over the place.

这篇关于反应|如何将FormikProps传递给一个组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆