formsreact-hook-formnext.js13zodmantine

I am using React-hook-form with Mantine MultiSelect Component and Zod and i am have issue with string type


  type UseControllerProps,
  useController,
  type FieldValues,
} from "react-hook-form";
import {
  MultiSelect as $MultiSelect,
  type MultiSelectProps as $MultiSelectProps,
} from "@mantine/core";

export type MultiSelectProps<T extends FieldValues> = UseControllerProps<T> &
  Omit<$MultiSelectProps, "value" | "defaultValue">;

export function MultiSelect<T extends FieldValues>({
  name,
  control,
  defaultValue,
  rules,
  shouldUnregister,
  onChange,
  ...props
}: MultiSelectProps<T>) {
  const {
    field: { value, onChange: fieldOnChange, ...field },
    fieldState,
  } = useController<T>({
    name,
    control,
    defaultValue,
    rules,
    shouldUnregister,
  });

  return (
    <$MultiSelect
      value={value}
      onChange={(e) => {
        fieldOnChange(e);
        onChange?.(e);
      }}
      error={fieldState.error?.message}
      {...field}
      {...props}
    />
  );
}

The component above is the MultiSelect that react-hook-form want to extends in order to be compatible with Zod. So my issue is that i have an array of objects :

  const dropDownResourcesValues = resources.map((x: any) => ({
    label: x.id.toString(),
    value: x.id.toString(),
  }));

 <MultiSelect
      style={{ width: "50%" }}
      required
      size="md"
      radius="md"
      label="Tags"
      withAsterisk
      placeholder="Please enter tags"
      name={"tags"}
      data={dropDownTagValues}
      control={control}
/>

needs to be string in order to pass the validation of Zod, but in the post request the values must be Numbers (expected type from BE)

Is there any way to extend the MultiSelectProps to except numbers as values ?


Solution

  • According to the documentation of the Mantine MultiSelect component, it doesn't seem to accept any other data formats except an array of strings or a defined object shape with value, label, and optional disabled field.

    What you can do instead is to use Zod's coercion operator to coerce the string input value into a number. This will give you an array of numbers when you submit the form.

    const schema = z.object({
      options: z.array(z.coerce.number())
    })