-
Hi! First, thank you for a great library! I've been using v5 successfully to create an internal library module of different form components, and things have worked well. I'm now trying to migrate the internal library to v6 but am struggling with moving away from In the below example the lines rvf.value and rvf.setValue fail in Typescript with:
What should I put as type there to the import { useField } from "@rvf/remix";
import { FieldValues } from "@rvf/core";
import { FormApi } from "@rvf/react";
type RvfDebugProps<FormInputData extends FieldValues> = {
rvf: FormApi<FormInputData>;
name: string; // TODO: what should this be?
};
export const RvfDebug = <FormInputData extends FieldValues>({
rvf,
name,
}: RvfDebugProps<FormInputData>) => {
// // In v5 I did this successfully:
// const { error, validate } = useField(name);
// const [value, setValue] = useControlField<string | null>(name, initialContent || "");
const { error, validate } = useField(name);
const value = rvf.value(name);
return (
<div>
<MyComponent
onContentUpdate={(_, updatedContent) => {
const cleanedContent = myClean(updatedContent);
if (cleanedContent !== value) {
rvf.setValue(name, cleanedContent);
validate();
}
}}
/>
</div>
);
}; Edit. I got it to compile with: name: Parameters<FormApi<FormInputData>["value"]>[0]; and rvf.setValue(
name,
cleanedContent as ReturnType<FormApi<FormInputData>["value"]>,
); but that's quite hacky, plus I'd really like to say " |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
+1 on this issue! |
Beta Was this translation helpful? Give feedback.
-
Hi! The best way to create abstractions in v6 is to use the scoping API. You could write your example like this: // You only need to depend directly on `@rvf/remix`
import { useField, FormScope } from "@rvf/remix";
// No "extends" because we can scope to anything
type RvfDebugProps<FormInputData> = {
scope: FormScope<FormInputData>;
};
export const RvfDebug = <FormInputData>({
scope,
}: RvfDebugProps<FormInputData>) => {
const field = useField(scope);
return (
<div>
<MyComponent
onContentUpdate={(_, updatedContent) => {
const cleanedContent = myClean(updatedContent);
if (cleanedContent !== value) {
// can use methods directly off of `field` -- don't even need the name
field.setValue(cleanedContent);
field.validate();
}
}}
/>
</div>
);
}; You would use it like this: <RvfDebug scope={form.scope("myField")} /> Also, given that this component is named RvfDebug, I'm assuming this isn't actually the field component itself -- just a helper util? In the actual controlled component, you'll want to make sure you're passing a |
Beta Was this translation helpful? Give feedback.
Hi! The best way to create abstractions in v6 is to use the scoping API. You could write your example like this: