TanStackT
TanStack3y ago
40 replies
full-green

creating a reusable styled form component

Hey, so I am working on creating a styled and aria friendly reusable form component using tanstack/react-form. I havent done that much yet because I am unsure of the best approach here. I am generally wondering if it is a bad approach to create a separate context for the form, and pass in formOptions. The plan is to create different styled form fields for a labeled input, checkbox etc with all predefined aria ids and styles. This is what I have so far, and it would be nice with some feedback if I am using the library correctly for this. I am also not completely sure if my type definition for the fromOptions is correct. Thanks for any help :)

type FormProps = HTMLAttributes<HTMLFormElement> & {
  formOptions: FormOptions<Record<string, unknown>, typeof zodValidator>;
};

type FormTextInputProps = HTMLAttributes<HTMLInputElement> & {
  name: string;
  label: string;
};

type FormComponentProps = ForwardRefExoticComponent<FormProps> & {
  TextInput: ForwardRefExoticComponent<FormTextInputProps>;
};
type FormContextProps = FormApi<Record<string, unknown>, typeof zodValidator>;

const FormContext = createContext<FormContextProps>({} as FormContextProps);

const Form = forwardRef<HTMLFormElement, FormProps>(
  ({ className, formOptions, ...props }, ref) => {
    const HeadlessForm = useForm({
      validatorAdapter: zodValidator,
      ...formOptions,
    });

    return (
      <FormContext.Provider value={HeadlessForm}>
        <HeadlessForm.Provider>
          <form
            className={className}
            onSubmit={(e) => {
              e.preventDefault();
              e.stopPropagation();
              void HeadlessForm.handleSubmit();
            }}
            ref={ref}
            {...props}
          />
        </HeadlessForm.Provider>
      </FormContext.Provider>
    );
  },
) as FormComponentProps;
Was this page helpful?