creativetimofficial / material-tailwind

@material-tailwind is an easy-to-use components library for Tailwind CSS and Material Design.
https://material-tailwind.com/
MIT License
3.74k stars 320 forks source link

Type error with react-hook-form (Select component) #642

Open bryanlundberg opened 7 months ago

bryanlundberg commented 7 months ago

I found an issue trying to use react-hook-form to validate the form, works with input components but not with the select component🤷‍♂️

Error gotten (select component):

Type '{ children: Element[]; onChange: ChangeHandler; onBlur: ChangeHandler; ref: RefCallBack; name: "location"; min?: string | number | undefined; ... 8 more ...; value: string; }' is not assignable to type 'Pick<SelectProps, "size" | "children" | "onChange" | "onSubmit" | "title" | "color" | "translate" | "slot" | "style" | "onClick" | "className" | "key" | "defaultChecked" | ... 261 more ... | "menuProps">'.
  Types of property 'onChange' are incompatible.
    Type 'ChangeHandler' is not assignable to type 'onChange'.
      Types of parameters 'event' and 'value' are incompatible.
        Type 'string | undefined' is not assignable to type '{ target: any; type?: any; }'.
import { IDialogFormSize } from "@/interfaces/DialogFormSize";
import {
  Button,
  Dialog,
  DialogBody,
  DialogFooter,
  DialogHeader,
  Input,
  Option,
  Select,
} from "@material-tailwind/react";
import React from "react";
import { useForm } from "react-hook-form";

export default function EditDismantleDetailsForm({
  onSubmitForm,
  size,
  handleOpen,
  dismantleDetails,
}: {
  dismantleDetails: any;
  size: IDialogFormSize;
  handleOpen: (size: IDialogFormSize) => void;
  onSubmitForm: (data: any) => void;
}) {

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const onSubmit = handleSubmit(async (form) => {
    try {
      console.log(form);
      return onSubmitForm(form);
    } catch (err) {}
  });

  return (
    <>
      <Dialog
        open={
          size === "xs" ||
          size === "sm" ||
          size === "md" ||
          size === "lg" ||
          size === "xl" ||
          size === "xxl"
        }
        size={size || "md"}
        handler={handleOpen}
      >
        <form onSubmit={onSubmit}>
          <DialogHeader>Edit details</DialogHeader>
          <DialogBody>
            <div className="flex flex-col gap-3">
              {/* more inputs */}
              <Select
                size="md"
                label="Location"
                value="Option2"
                {...register("location", {
                  required: false,
                })}
              >
                <Option value="Option1">1</Option>
                <Option value="Option2">2</Option>
                <Option value="Option3">3</Option>
              </Select>
            </div>
          </DialogBody>
          <DialogFooter>
            <Button
              variant="text"
              color="red"
              onClick={() => handleOpen(null)}
              className="mr-1 transition duration-200"
            >
              <span>Cancel</span>
            </Button>
            <Button
              type="submit"
              className="hover:shadow-sm transition duration-200"
              color="green"
            >
              <span>Ok</span>
            </Button>
          </DialogFooter>
        </form>
      </Dialog>
    </>
  );
}
fredrikgustn commented 5 months ago

I have a similar issue that seems to be related to the react version. I have the same issue with the provided sample pro templates where it's not possible to build however it works when running in developer mode.

Depending on which react version that I use, I can get different results and different incopability problems. This is what I get when I use the default version from the blog-tailwind-nextjs sample project. I tested it to first rule out problem in my own code.

./src/app/blog-posts.tsx:39:8
Type error: Type '{ children: string; color: "gray"; className: string; size: "sm"; }' is missing the following properties from type 'Pick<ButtonProps, "children" | "color" | "translate" | "slot" | "style" | "title" | "onChange" | "onClick" | "className" | "key" | "defaultChecked" | "defaultValue" | ... 261 more ... | "loading">': placeholder, onPointerEnterCapture, onPointerLeaveCapture

  37 |   return (
  38 |     <section className="w-full max-w-6xl mx-auto flex flex-col items-center px-4 py-20">
> 39 |       <Button color="gray" className="mb-3" size="sm">
     |        ^
  40 |         BLOG
  41 |       </Button>
  42 |       <Typography variant="h3" className="text-center" color="blue-gray">
unloop commented 4 months ago

@bryanlundberg You need to add controller on top of component from react-hook-form.

import { FC } from "react";
import { Controller, FormProvider, useForm } from "react-hook-form";
import { Option, Select } from "@material-tailwind/react";

export interface IProps {
}

export const ProfileForm: FC<IProps> = () => {
  const methods = useForm();

  async function onSubmit(data: any) {
    console.log("Submit:", data);
  }

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Controller
          name="data"
          control={methods.control}
          render={({ field: { onChange, value } }) => (
            <Select
              name="data"
              label="Select value"
              value={value}
              onChange={onChange}>
              <Option value="demo1">Demo1</Option>
              <Option value="demo2">Demo2</Option>
            </Select>
          )}/>
      </form>
    </FormProvider>
  )
}