Inserting Shadcn Slider/DatePicker into react-hook-form
—
I couldn’t find clear examples of using Slider and DatePicker components from Shadcn with react-hook-form
. Here’s how I implemented both.
Slider
First, create a small wrapper component around Shadcn’s Slider
:
import { useEffect } from "react";
import { Slider } from "@/components/ui/slider";
type Props = {
value: number;
onChange: (value: number) => void;
};
export default function Ratio({ value, onChange }: Props) {
useEffect(() => {
if (!value) {
onChange(0.5);
}
}, [value, onChange]);
return (
<Slider
min={0}
max={1}
step={0.01}
defaultValue={[value ?? 0.5]}
onValueChange={(vals) => onChange(vals[0])}
/>
);
}
Then use it in your form like this:
<FormField
control={form.control}
name="slider"
render={({ field }) => (
<FormItem>
<FormLabel>Slider</FormLabel>
<FormControl>
<Ratio
value={field.value}
onChange={(value) => form.setValue("slider", value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
DatePicker
This one is more complex. I keep the date range as two fields in a single object: startDate and endDate.
Step 1: Create a wrapper around your custom DateRangePicker component.
import { useState } from "react";
import { DateRange } from "react-day-picker";
import DateRangePicker from "@/components/DateRangePicker";
type Props = {
formValue: {
startDate: string;
endDate: string;
};
onChange: (value: DateRange | undefined) => void;
};
export default function DateField({ formValue, onChange }: Props) {
const [date, setDate] = useState<DateRange | undefined>({
from: formValue?.startDate ? new Date(formValue.startDate) : undefined,
to: formValue?.endDate ? new Date(formValue.endDate) : undefined,
});
function handleSelectDate(selected: DateRange | undefined) {
setDate(selected);
onChange(selected);
}
return (
<DateRangePicker
date={date}
setDate={handleSelectDate}
fromDate={new Date()}
/>
);
}
Step 2: Use it in the form
<FormField
control={form.control}
name="dateRange"
render={({ field }) => (
<FormItem>
<FormLabel>Date Range</FormLabel>
<DateField
formValue={field.value}
onChange={(value) => setDateRange(value)}
/>
<FormMessage />
</FormItem>
)}
/>
Step 3: Define the handler
const setDateRange = useCallback((value: DateRange | undefined) => {
if (!value?.from) {
form.setValue("dateRange", {
startDate: "1970-01-01",
endDate: "1970-01-01",
});
return;
}
const start = format(value.from, "yyyy-MM-dd");
const end = value.to ? format(value.to, "yyyy-MM-dd") : start;
form.setValue("dateRange", {
startDate: start,
endDate: end,
});
}, [form]);
There might be cleaner ways to do this, but this setup works well and integrates smoothly with react-hook-form
.
Hope it helps!