I want to register the selected object using Zod and react-forms

I have quite a large component.
1 Reply
mac
macOP2y ago
I want to register the selected guild id into the react form . I just have no clue how since the dropdown is from headless ui Validation Schema
const validationSchema = z.object({
name: z
.string()
.min(1, { message: "A name is required" })
.min(5, { message: "Community Names has to be between 5-32 characters" })
.max(32, { message: "Community Names has to be between 5-32 characters" }),
slug: z
.string()
.regex(/^[a-z0-9_]+$/, {
message:
"Community URL can only contain lowercase letters, numbers and underscores",
})
.min(1, { message: "A URL is required" })
.min(5, { message: "Community URL has to be between 5-32 characters" })
.max(32, { message: "Community URL has to be between 5-32 characters" }),
description: z
.string()
.min(1, { message: "A description is required" })
.max(256, { message: "Description has to be less than 256 characters" }),
image: z
.custom<FileList>()
.refine((file) => file?.length == 1, "Image is required.")
.transform(([file]) => file)
.refine((file) => file?.size <= MAX_FILE_SIZE, `Max image size is 2MB.`)
.refine(
(file) => ACCEPTED_IMAGE_TYPES.includes(file?.type),
"Only .jpg, .jpeg, .png and .webp formats are supported."
),
guildId: z.string().min(1, { message: "A discord server is required" }),
});
const validationSchema = z.object({
name: z
.string()
.min(1, { message: "A name is required" })
.min(5, { message: "Community Names has to be between 5-32 characters" })
.max(32, { message: "Community Names has to be between 5-32 characters" }),
slug: z
.string()
.regex(/^[a-z0-9_]+$/, {
message:
"Community URL can only contain lowercase letters, numbers and underscores",
})
.min(1, { message: "A URL is required" })
.min(5, { message: "Community URL has to be between 5-32 characters" })
.max(32, { message: "Community URL has to be between 5-32 characters" }),
description: z
.string()
.min(1, { message: "A description is required" })
.max(256, { message: "Description has to be less than 256 characters" }),
image: z
.custom<FileList>()
.refine((file) => file?.length == 1, "Image is required.")
.transform(([file]) => file)
.refine((file) => file?.size <= MAX_FILE_SIZE, `Max image size is 2MB.`)
.refine(
(file) => ACCEPTED_IMAGE_TYPES.includes(file?.type),
"Only .jpg, .jpeg, .png and .webp formats are supported."
),
guildId: z.string().min(1, { message: "A discord server is required" }),
});
Dropdown Component
{ownedGuilds?.data ? (
<Listbox value={selected} onChange={setSelected} name="guild" >
<div className="relative ">
<Listbox.Button
className={`btn-input flex flex-row justify-between py-2 pl-3 pr-3 text-left ${
errors.guildId ? "btn-input-error" : ""
} `}
>
<span
className="block truncate text-neutral-500"
>
{selected?.name ? selected.name : "Select a server"}
</span>

<span className="pointer-events-none flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-neutral-500"
aria-hidden="true"
/>
</span>
</Listbox.Button>
{errors.guildId && (
<p className="mt-2 text-xs italic text-red-500">
{errors.guildId?.message}
</p>
)}
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute mt-1 max-h-36 w-full overflow-auto rounded-md border border-neutral-700 bg-black py-2 leading-5 text-neutral-500 placeholder-neutral-500 duration-300 hover:border-neutral-400 focus:border-neutral-400 focus:text-gray-300 focus:placeholder-transparent focus:outline-none focus:ring-neutral-400 sm:text-sm">
{ownedGuilds.data.map((guild: DiscordGuild) => (
<Listbox.Option
key={guild.id}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-10 pr-4 ${
active
? "bg-neutral-800 text-neutral-300"
: "text-neutral-500"
}`
}
value={guild}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected ? "font-medium" : "font-normal"
}`}
>
{guild.name}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-500">
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
) : (
<div> loading... </div>
)}
{ownedGuilds?.data ? (
<Listbox value={selected} onChange={setSelected} name="guild" >
<div className="relative ">
<Listbox.Button
className={`btn-input flex flex-row justify-between py-2 pl-3 pr-3 text-left ${
errors.guildId ? "btn-input-error" : ""
} `}
>
<span
className="block truncate text-neutral-500"
>
{selected?.name ? selected.name : "Select a server"}
</span>

<span className="pointer-events-none flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-neutral-500"
aria-hidden="true"
/>
</span>
</Listbox.Button>
{errors.guildId && (
<p className="mt-2 text-xs italic text-red-500">
{errors.guildId?.message}
</p>
)}
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute mt-1 max-h-36 w-full overflow-auto rounded-md border border-neutral-700 bg-black py-2 leading-5 text-neutral-500 placeholder-neutral-500 duration-300 hover:border-neutral-400 focus:border-neutral-400 focus:text-gray-300 focus:placeholder-transparent focus:outline-none focus:ring-neutral-400 sm:text-sm">
{ownedGuilds.data.map((guild: DiscordGuild) => (
<Listbox.Option
key={guild.id}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-10 pr-4 ${
active
? "bg-neutral-800 text-neutral-300"
: "text-neutral-500"
}`
}
value={guild}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected ? "font-medium" : "font-normal"
}`}
>
{guild.name}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-500">
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
) : (
<div> loading... </div>
)}
On change
const [selected, setSelected] = useState(
ownedGuilds?.data ? ownedGuilds?.data?.[0] : "...loading"
);
const [selected, setSelected] = useState(
ownedGuilds?.data ? ownedGuilds?.data?.[0] : "...loading"
);
I think thats everything I should add im trying to register the selected.id into the validation schema (zod)
Want results from more Discord servers?
Add your server