Replies: 8 comments 11 replies
-
You're using Person component as a generic component therefore "setValue" only knows type value following the generic type of "TFormValues". In case you want to set specific field value of "TFormValues", you need to pass it to Person component too. |
Beta Was this translation helpful? Give feedback.
-
I too would like to use reusable components. https://codesandbox.io/s/useformreturn-with-generics-db4i6m?file=/src/App.tsx |
Beta Was this translation helpful? Give feedback.
-
aw bad luck, thanks anyway
…On Tue, Nov 15, 2022 at 2:01 PM Riku Kobayashi ***@***.***> wrote:
Unfortunately I haven't been able to resolve this.
Currently, I don't reuse components, but define a new component every time
I need it.
—
Reply to this email directly, view it on GitHub
<#8311 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AV33AU54MVTLVDV2WZYPKV3WIOJTZANCNFSM5VE3MVSA>
.
You are receiving this because you commented.Message ID:
<react-hook-form/react-hook-form/repo-discussions/8311/comments/4146807@
github.com>
|
Beta Was this translation helpful? Give feedback.
-
Is there any solution to this at this moment? |
Beta Was this translation helpful? Give feedback.
-
Going back a few years now I've found that react-hook-form internal types are a hassle and that every time I came up with a working solution with generics it'd get broken in a subsequent patch release. I recall looking at the diffs (at least 2+ years ago now) and remember that what I found led me to conclude it wasn't worth wasting time trying to maintain them. A tip though -- With react-hook-form I have had far more success using discriminated unions to reuse form fields between create and update contexts because they definitively select between "type A" vs. "type B". (I assume this might be aligned with your use-case per your limited example) Here's an example from a boilerplate I'm putting together for ts-rest:
Corresponding fields are the following and there are no type issues with current release versions of everything:
With this I didn't have to repeat the fields for each create vs. update case. I actually tried with generics once again and sure enough there were type issues. I am not actually using the |
Beta Was this translation helpful? Give feedback.
-
@firxworx I have found a way to work with reusable input components using generics in RHF (https://github.com/orgs/react-hook-form/discussions/9789#discussioncomment-4711065). The trick is to check the generic constraint again. As mentioned in the linked discussion, I still haven't figured out why this is needed. Example: // EmailInput.tsx
import {
Control,
Controller,
UseFormRegister,
UseFormSetValue,
} from 'react-hook-form';
// The restriction of the reusable component.
// In this case, we want to use this component in forms which have an `email: string` field
type FieldValuesWithEmail = {
email: string;
};
// We restrict T to have the email field, and use it to pass to generics such as UseFormRegister, UseFormSetValue, Control, etc.
// HOWEVER, while this is the correct approach, this will still result in type errors.
// type Props<T extends FieldValuesWithEmail> = {
// register: UseFormRegister<T>;
// setValue: UseFormSetValue<T>;
// control: Control<T>;
// }
// To fix the above, we have to check for the generic constraint again in each property.
// I have not found an explanation yet why this is necessary.
type Props<T extends FieldValuesWithEmail> = {
register: T extends FieldValuesWithEmail ? UseFormRegister<T> : never;
setValue: T extends FieldValuesWithEmail ? UseFormSetValue<T> : never;
control: T extends FieldValuesWithEmail ? Control<T> : never;
};
export const EmailInput = <T extends FieldValuesWithEmail>({
register,
setValue,
control,
}: Props<T>) => {
// Example usage of get value
setValue('email', '');
return (
<>
{/* Example usage of register */}
<input {...register('email')} />
{/* Example usage of control */}
<Controller control={control} name="email" render={() => <></>} />
</>
);
}; // App.tsx
export const App = () => {
const { register, setValue, control } = useForm<{
email: string;
username: string;
password: string;
}>();
return (
<form>
{/* All methods can be passed without type error */}
<EmailInput register={register} setValue={setValue} control={control} />
</form>
);
} |
Beta Was this translation helpful? Give feedback.
-
has anyone found a way to use reusable components with RHF? type RowData = { color?: string; value: T };
const { fields, append, remove } = useFieldArray<RowData>({
control,
name: props.name,
}); |
Beta Was this translation helpful? Give feedback.
-
Hi, I created a PR that demonstrates a Lens approach for building reusable components with TypeScript support #12284 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Person
component is reused in two different forms:Person.tsx
SimpleForm.tsx
ComplexForm.tsx
types.ts
utils.ts
It works beautifully, but if I try to
setValue
inPerson
, TypeScript throws an error:How could I fix this?
CodeSandbox
Beta Was this translation helpful? Give feedback.
All reactions