Reputation: 635
I followed everything from documentation and watched the tutorial by Ben Awad on YouTube. And still, I cannot get it to work.
const TextField = (props: FieldHookConfig<{}>) => {
const [field] = useField(props);
return (
<div>
<input {...field} {...props}/>
</div>
);
};
I used the FieldHookConfig
as the type for the props because the useField
is expecting a string
or the FieldHookConfig
base on the Field.d.ts file. yet typescript is still not happy.
it complains right in this line <input {...field} {...props}/>
(property) JSX.IntrinsicElements.input: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
Type '{ ref?: string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined; key?: string | number | undefined; ... 289 more ...; innerRef?: ((instance: any) => void) | undefined; } | { ...; } | { ...; }' is not assignable to type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
Type '{ ref?: string | ((instance: HTMLSelectElement | null) => void) | RefObject<HTMLSelectElement> | null | undefined; key?: string | number | undefined; ... 269 more ...; checked?: boolean | undefined; }' is not assignable to type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
Type '{ ref?: string | ((instance: HTMLSelectElement | null) => void) | RefObject<HTMLSelectElement> | null | undefined; key?: string | number | undefined; ... 269 more ...; checked?: boolean | undefined; }' is not assignable to type 'ClassAttributes<HTMLInputElement>'.
Types of property 'ref' are incompatible.
Type 'string | ((instance: HTMLSelectElement | null) => void) | RefObject<HTMLSelectElement> | null | undefined' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'.
Type '(instance: HTMLSelectElement | null) => void' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'.
Type '(instance: HTMLSelectElement | null) => void' is not assignable to type '(instance: HTMLInputElement | null) => void'.
Types of parameters 'instance' and 'instance' are incompatible.
Type 'HTMLInputElement | null' is not assignable to type 'HTMLSelectElement | null'.
Type 'HTMLInputElement' is missing the following properties from type 'HTMLSelectElement': length, options, selectedIndex, selectedOptions, and 4 more.ts(2322)
Upvotes: 17
Views: 17061
Reputation: 179
@Pavlo
No need to redefine 'FieldHookConfig' again and add your custom fields.
Simply, you can extend 'FieldHookConfig' using the & operator like this:
type ExtendedFieldHook = FieldHookConfig<string> & { label: string }
And then, the component will look like:
export const TextInput = ({ label, ...props }: ExtendedFieldHook) => {
const [field, meta] = useField(props);
return (
<div className=" my-3">
{meta.touched && meta.error ? (
<>
<input className="form-control" {...field} {...props} />
<div className="error error-check text-danger">{meta.error}</div>
</>
) : (
<input className="form-control" {...field} {...props} />
)}
</div>
);
};
Upvotes: 0
Reputation: 21
This is how I solved this issue, using formik docs
Actually Typescript was satisfied just after I added 'name: string;' to my InputProps.
type InputProps = {
label: string;
name: string;
validate?: (value: any) => undefined | string | Promise<any>;
type?: string;
multiple?: boolean;
value?: string;
};
export const TextInput = ({ label, ...props }: InputProps) => {
const [field, meta] = useField(props);
return (
<div className=" my-3">
{meta.touched && meta.error ? (
<>
<input className="form-control" {...field} {...props} />
<div className="error error-check text-danger">{meta.error}</div>
</>
) : (
<input className="form-control" {...field} {...props} />
)}
</div>
);
};
Upvotes: 2
Reputation: 336
For anyone still experiencing the same issue try the following:
import { ClassAttributes, InputHTMLAttributes } from "react"
import { useField, FieldHookConfig } from "formik"
const TextField = (props: InputHTMLAttributes<HTMLInputElement> & ClassAttributes<HTMLInputElement> & FieldHookConfig<string>) => {
const [field] = useField(props);
return (
<div>
<input {...field} {...props}/>
</div>
);
};
And if you have a destructured props you could do this:
type TextFieldProps = {
label: string;
};
const TextField = ({label, ...props}: TextFieldProps & InputHTMLAttributes<HTMLInputElement> &
ClassAttributes<HTMLInputElement> &
FieldHookConfig<string>) => {
const [field] = useField(props);
return (
<div>
<input {...field} {...props}/>
</div>
);
};
Upvotes: 7
Reputation: 380
Just to add to the above, the useField()
documentation referenced above shows label
being included in the MyTextField
properties. In order to make this type of call:
<TextField name="firstName" type="text" placeholder="Jane" label="First Name" />
add the following interface:
interface OtherProps {
label : string
}
Then change the first line of the function expression above to:
const TextField = (props : OtherProps & FieldHookConfig<string>) => {
You can then reference the passed label
by calling props.label
within the function's return block like this, for example:
<label htmlFor={props.id || props.name}>{props.label}</label>
Upvotes: 12
Reputation: 186
There are 2 problems, firstly, you cannot spread the props
variable on the <input>
element, due to the incompatible types (as specified in the error). Secondly, your generic type for FieldHookConfig
shouldn't be {}
, rather it should be string
So to fix it, suppose you are using your <TextField>
element like so
<TextField
name="firstName"
type="text"
placeholder="Jane"
/>
Then inside your TextField
definition, you will write
const TextField = (props: FieldHookConfig<string>) => {
const [field] = useField(props);
return (
<div>
{/* no need to pass the name field because Formik will accept
that prop internally and pass it to the field variable */}
<input {...field} placeholder={props.placeholder} type={props.type} />
</div>
);
};
Upvotes: 17