I’m working on a Next.js project utilizing Shadcn-ui components, specifically Inputs and a Date Picker within a Form. The form submission is handled by a formaction that processes the submitted data. A live, simplified version of my issue can be explored HERE.
Issue: When selecting a date using the Date Picker
, the selectedDate
correctly logs to the console within the onSelect
event in the Date Picker
component (date-picker-form.tsx
). However, when I try to access this date value in my action handler (actions.ts), it’s logged as null
. I’m trying to understand why the date value isn’t being passed through correctly.
actions.ts
'use server';
import { redirect } from 'next/navigation';
export async function createDbEntry(formData: FormData) {
const data = {
text_input: formData.get('text_input') as string,
datepicker: formData.get('datepicker') as string,
};
console.log(data); // Here, `datepicker` is logged as `null`
redirect('/');
}
date-picker-form.tsx
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { CalendarIcon } from '@radix-ui/react-icons';
import { format } from 'date-fns';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Calendar } from '@/components/ui/calendar';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { Input } from '@/components/ui/input';
import { createDbEntry } from '@/lib/actions';
const FormSchema = z.object({
text_input: z.string(),
datepicker: z.date({
required_error: 'A date of birth is required.',
}),
});
export function DatePickerForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
});
return (
<Form {...form}>
<form className="space-y-8">
{/* Input Field */}
<FormField
control={form.control}
name="text_input"
render={({ field }) => (
<FormItem>
<FormLabel>Text Input</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* Datepicker Field */}
<FormField
control={form.control}
name="datepicker"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Date Picker</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={'outline'}
className={cn(
'w-[240px] pl-3 text-left font-normal',
!field.value && 'text-muted-foreground'
)}
>
{field.value ? (
format(field.value, 'PPP')
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={(selectedDate) => {
console.log('selectedDate', selectedDate); // Here date logs fine
field.onChange(selectedDate);
}}
disabled={(date) =>
date > new Date() || date < new Date('1900-01-01')
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormDescription>
Your date of birth is used to calculate your age.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button formAction={createDbEntry}>Submit</Button>
</form>
</Form>
);
}
Attempts to Resolve:
- Verified that other form data, like text inputs, are captured correctly.
- Ensured field.onChange is called with the correct date within onSelect.
Could anyone help me identify why the date value is null when accessed in the action handler? Is there a step I’m missing to ensure the date value is correctly passed through the form submission process?