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.
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;
}
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!!
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>
)}
/>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With