engineering

How To Implement A Date Picker In React

How To Implement A Date Picker In React

We have third-party libraries that we can integrate into our project to extend the existing functionality of date pickers. In this article, let's explore date pickers in React.

Kaushal Joshi

Kaushal Joshi

May 23, 2025 18 min read

Forms in React! I can go on and on writing about this. Managing different states, different types of input, validating them, and displaying correct loading or error states becomes overwhelming at one point. Most of the things I mentioned have become manageable, thanks to libraries like React Hook Form and Zod. But one thing remains cumbersome and still requires special attention: handling date inputs.

Yes, HTML provides a native date picker with <input /> and it does its job. But honestly, it is very limited and can't do much beyond selecting a date, time, or month. And styling the native date picker is a different quest in itself.

In React, we have third-party libraries that we can integrate into our project to extend the existing functionality of date pickers. In this article, let's explore date pickers in React. We will also see the native date picker and its limitations. Then we will also see some NPM libraries that you can use. And finally, we'd focus on react-day-picker, the library best suited to be used as a date picker in React.

The Native Date Picker

HTML provides a native date picker, and you must have used it at least once in your project -- before you started to look for a different approach. It's simple to implement, and the browser handles the UI for you. Let me remind you how it works:

export default function DatePicker() {
  return (
    <div>
      <label htmlFor="bday">Birth date:</label>
      <input type="date" id="bday" name="bday" />
    </div>
  );
}

This is how it looks:

Pretty straightforward. You get a popover that lets you select the date without writing a single line of code. It gives you a prettified human-readable string that you can easily convert to Date object with new Date() constructor.

Limitations with the native date picker

However, there are many limitations with the native date picker.

  1. Limited styling: Customizing the appearance of the native date picker is notoriously difficult and inconsistent across browsers. Want to change colors, font, or the layout? All the best!

  2. Inconsistent UI: The look and feel of the date picker can vary significantly between Chrome, Firefox, Safari, and other browsers. This can lead to a jarring user experience on your website.

  3. Lack of Advanced Features: Need to select date ranges? Disable specific dates? Implement custom date formatting? The native date picker simply doesn't offer these functionalities out of the box.

  4. Localization Challenges: While browsers handle basic localization, more complex scenarios like custom date formats or specific regional calendar behaviors can be tricky to implement reliably.

The native date picker is only good for basic projects. But your project is extraordinary and needs special attention to detail, right? Going beyond the basics that require a beautiful UI or complex logic is difficult with the native date picker. And hence, there exist third-party libraries that do the same for you.

Overview of Popular Date Picker Libraries in React

Before we explore react-day-picker, I want to quickly go through some other libraries that do the same. If you find any other library that fits your needs better, feel free to use it.

react-datepicker

A well-established library with a rich feature set, including support for date ranges, inline display, and time selection as well.

import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

const ReactDatepickerExample = () => {
  const [startDate, setStartDate] = React.useState(new Date());
  return <DatePicker selected={startDate} onChange={(date) => setStartDate(date)} />;
};

export default ReactDatepickerExample;
  • Pros: Mature ecosystem, excellent documentation, and wide adoption.

  • Cons: Heavier bundle size, requires careful styling to match your design system.

You can check out react-datepicker on NPM here.

Material UI Date Picker

This library is part of the MUI component library and integrates tightly with MUI's design system. If you're using Material UI in your project, just go with this library right away.

import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';

const MUIDatePickerExample = () => {
  const [value, setValue] = React.useState(null);

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <DatePicker value={value} onChange={(newValue) => setValue(newValue)} />
    </LocalizationProvider>
  );
};

export default MUIDatePickerExample;
  • Pros: Consistent design, rich feature set, strong TypeScript support.

  • Cons: Heavier dependency if you’re not using MUI for the rest of your UI.

You can check out Material UI Date Picker on NPM here.

react-calendar

A simpler, lightweight option ideal for straightforward date picking.

import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';

const ReactCalendarExample = () => {
  const [date, setDate] = React.useState(new Date());
  return <Calendar onChange={setDate} value={date} />;
};

export default ReactCalendarExample;
  • Pros: Lightweight, easy to use, minimal setup.

  • Cons: Lacks some advanced features like date ranges and complex event handling.

You can check out react-calendar on NPM here.

react-day-picker

This is our topic for the day! It is lightweight, feature-rich, and highly customizable. This is perfect for all the complex use cases where you need fine-grained control over date selection and styling.

The only downside I see with react-day-picker is that there's a learning curve, and you need to spend more time setting up things for advanced use cases. But with great power comes great responsibility. So I am fine with it.

What is React Day Picker?

react-day-picker is a highly customizable and accessible date picker component library for React. It lets you create date pickers, calendars, and date inputs while giving you granular control over their look and feel.

What are the features of react-day-picker?

  • Flexible Rendering: You have complete control over how each day, week, and month is rendered. This allows for highly customized UIs.

  • Multiple Selection Modes: Supports single date selection, multiple date selection, and date range selection out of the box.

  • Date Formatting and Parsing: Offers powerful utilities for formatting and parsing dates according to different locales and patterns.

  • Accessibility: Built with accessibility in mind, ensuring a good experience for all users, including those using assistive technologies.

  • Customizable Styling: While it doesn't come with default styling, it provides clear and well-structured CSS classes that you can easily target and customize to match your application's design.

  • Localization Support: Designed to handle different languages and regional date formats effectively.

  • Timezone Considerations: While the library itself focuses on date selection, it provides the flexibility to integrate with timezone management libraries if needed.

  • Custom Components: You can also create custom components for each section of the date picker. Very useful when you are building your own design system.

With over 500k weekly NPM downloads and over 7,000 GitHub stars as of writing this article, react-day-picker is undoubtedly a great choice for your project.

How react-day-picker stands out:

We saw some date picker libraries in the last section. I have used some of them in my projects before, but I ended up choosing react-day-picker as my go-to React day picker library. Let me explain why.

react-day-picker differentiates itself by being less opinionated about styling compared to other libraries. It gives you raw power and flexibility to build a date picker that looks and behaves exactly as you want, without being constrained by pre-defined themes. This makes it an excellent choice for projects with custom design systems or themes.

Even projects like shadcn/ui prefer react-day-picker for the same.

How to install react-day-picker in your React Application?

You can install react-day-picker simply by installing it as a dependency in your existing React project:

npm i react-day-picker

yarn add react-day-picker

pnpm add react-day-picker

Getting Started with React Day Picker

Let's start with a simple example of how to integrate react-day-picker for single date selection.

import React, { useState } from 'react';
import { DayPicker } from 'react-day-picker';
import 'react-day-picker/dist/style.css';

export default function SingleDatePicker() {
  const [selectedDate, setSelectedDate] = useState(undefined);

  return (
    <div>
      <h2>Select a Date</h2>
      <DayPicker
        mode="single"
        selected={selectedDate}
        onSelect={setSelectedDate}
      />
      {selectedDate ? (
        <p>You selected: {selectedDate.toLocaleDateString()}</p>
      ) : (
        <p>Please select a date.</p>
      )}
    </div>
  );
}

This is how it'd render:

  • First, we defined a local state to store the date: selectedDate.

  • Then we imported the <DatePicker /> component and its default styles. We use the single mode as we want to select a single date.

  • The selected prop holds the currently selected date (i.e., selectedDate), and the onSelect prop updates the state with the newly selected date. It is called whenever the user clicks on a day.

NOTE: Don't forget to import the default styles

Select multiple dates

To allow users to select multiple dates, we can use mode="multiple" and manage the selceted prop as an array of Date objects.

export default function MultiDatePicker() {
  const [selectedDates, setSelectedDates] = useState([]);

  return (
    <DayPicker
      mode="multiple"
      selected={selectedDates}
      onSelect={setSelectedDates}
    />
  );
}

Select a date range

For selecting a range of dates, we use mode="range" and the selected prop will be an object with from and to properties. Both from and to can be Date objects or undefined.

export default function RangeDatePicker() {
  const [selectedRange, setSelectedRange] = useState(undefined);

  return (
    <DayPicker
      mode="range"
      selected={selectedRange}
      onSelect={setSelectedRange}
    />
  );
}

Disabling specific dates

You can disable specific dates using the disabled prop. This prop accepts an array of Date objects or a function that takes a Date object and returns a boolean indicating whether the date should be disabled.

export default function DisabledDatePicker() {
  const [selectedDate, setSelectedDate] = useState(undefined);
  const disabledDates = [
    new Date(2025, 4, 15), // May 15th, 2025 (month is 0-indexed)
    new Date(2025, 4, 20),
  ];

  // Disable Sundays and Saturdays
  const isWeekend = (date) => date.getDay() === 0 || date.getDay() === 6;

  return (
   <DayPicker
     mode="single"
     selected={selectedDate}
     onSelect={setSelectedDate}
     disabled={[...disabledDates, isWeekend]}
   />
  );
}

Specify minimum and maximum dates

You can restrict the selectable date range using the minDate and maxDate props.

export default function MinMaxDatePicker() {
  const [selectedDate, setSelectedDate] = useState(undefined);
  const minDate = new Date(2025, 4, 10);
  const maxDate = new Date(2025, 4, 25);

  return (
    <DayPicker
      mode="single"
      selected={selectedDate}
      onSelect={setSelectedDate}
      minDate={minDate}
      maxDate={maxDate}
    />
  );
}

Customizing The Calendar

In this section, let's see how you can customize various sections of the calendar built using react-day-picker.

Show dates outside of the month

This prop lets you decide whether you want to display outside days. Days that are in the next month or the previous month. By default, it is false.

<DayPicker mode="single" showOutsideDays />

Show week numbers

This prop lets you decide whether you want to display the week numbers column. The weeks are numbered according to the local week index.

<DayPicker mode="single" showWeekNumber />

Show multiple months

You can decide how many months you want to display when the date picker is displayed. It is useful when you want to let the user select date ranges.

DayPicker mode="range" numberOfMonths={2} />

You can pass the animate property along with this, so that the navigation between pages is smoother. You can pass this property regardless of whether you are using numberOfMonths.

Define caption layout

You can decide the layout of the caption of the calendar. By default, it will just be a string that displays the month and the year.

  1. label: Display the month and the year as a label. Change the label with the formatCaption formatted.

    <DayPicker captionLayout="label" mode="single" /> // Default option, no need to mention
  2. dropdown: Display the dropdown for both month and year.

    <DayPicker captionLayout="dropdown" endMonth mode="single" startMonth />
  3. dropdown-months: Display only the dropdown for the months.

    <DayPicker captionLayout="dropdown-months" endMonth mode="single" startMonth />
  4. dropdown-years: Display only the dropdown for the years.

    <DayPicker captionLayout="dropdown-years" endMonth mode="single" startMonth />

Localization & Timezones

react-day-picker truly shines when it comes to localization. You can easily customize the display of month and weekday names, as well as the first day of the week, by providing custom formatting functions. You can extend the functionality by using libraries like date-fns or even built-in toLocaleDateString() method.

Selecting timezone

You can use the timeZone prop to define the time zone for your dates. The time zone can be specified as either an IANA time zone identifier or a UTC offset.

<DayPicker timeZone="UTC" /> // Use Coordinated Universal Time
<DayPicker timeZone="Pacific/Kiritimati" /> // Use Line Islands Time
<DayPicker timeZone="+02:00" /> // Use UTC+2
<DayPicker mode="single" timeZone="Asia/Calcutta" /> // Use Indian Time 

Select calendar type

react-day-picker also allows you to choose between calendar type: Gregorian or Persian. If you want to use the Persian calendar, you must import the <DatePicker /> component form react-day-picker/persian.

import { DayPicker } from "react-day-picker/persian";

<DayPicker mode="single" timeZone="UTC" />

Select a locale for the date picker

You can also select a locale for your date picker to follow.

<DayPicker mode="single" locale="fr"  />

Visit date-fns documentation to get a list of all supported locales.

Select the starting day of the week

You can specify which day you want to be the starting day of the week. In most countries, either Sunday or Monday is considered the first day of the week. react-day-picker selects the first day of the week based on your browser locale. But you can customize it as well:

<DayPicker mode="single" weekStartsOn={3} /> // Wednesday

weekStartsOn accepts a number between 0 and 6. Here, 0 stands for Sunday, 1 for Monday, and so on.

Select numerals language

You can also get more personal and gain even more granular control of your date picker by specifying the numeral system to be used to format dates.

<DayPicker mode="single" numerals="deva" />

Visit react-day-picker documentation to get a list of all available numerals.

Date Picker Helper Functions

The react-day-picker library provides plenty of helper functions to attach on various triggers in the date picker. We saw onSelect in one of our previous examples. Let's quickly go through some other functions as well.

  1. onDayBlur: Triggered when a day is blurred.

  2. onDayClick: Triggered when the user clicks on a day.

  3. onDayFocus: Triggers when a day is focused.

  4. onDayKeyDown: Triggers whenever a key is pressed on a day.

  5. onDayMouseEnter: Triggers whenever the mouse enters a day.

  6. onDayMouseLeave: Opposite to onDayMouseEnter, this triggers whenever the cursor leaves the day

  7. onMonthChange: Triggers whenever the user navigates between months

  8. onNextClick: Triggers when the next month button is clicked.

  9. onPrevClick: Triggers when the previous month button is clicked.

Integrating with React Hook Form and Zod

Integrating react-day-picker with form libraries like React Hook Form and validation libraries like Zod allows you to manage your date inputs within a robust form management system.

Here's an example of integrating with React Hook Form & Zod. If you are following along, make sure you install both libraries.

import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { DayPicker } from 'react-day-picker';
import 'react-day-picker/dist/style.css';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';

const schema = z.object({
  eventDate: z.date({ required_error: 'Event date is required.' }),
});

export default function FormWithDatePicker() {
  const { handleSubmit, control, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
  });

  const onSubmit = (data) => {
    console.log('Form Data:', data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="eventDate">Event Date:</label>
        <Controller
          name="eventDate"
          control={control}
          render={({ field }) => (
            <DayPicker
              mode="single"
              selected={field.value}
              onSelect={field.onChange}
            />
          )}
        />
        {errors.eventDate && <p style={{ color: 'red' }}>{errors.eventDate.message}</p>}
      </div>
      <button type="submit">Submit</button>
    </form>
  );
}

Let's understand what we wrote:

  1. We use the useForm hook from React Hook Form.

  2. We define a Zod schema to validate the eventDate field, ensuring it's a date and is required. The zodResolver is used to integrate this schema with React Hook Form.

  3. The Controller component connects the DayPicker with the form state.

  4. The render prop of Controller receives the field object, which contains value and onChange that we pass to the selected and onSelect props of DayPicker, respectively.

  5. We can then access form state and validation errors through the formState object.

Styling React Day Picker Component

The react-day-picker library provides several ways to style your component.

Use classname to directly apply classes to the root

The most straightforward way to style react-day-picker is by using the className prop. This works just like the standard className prop on any HTML element in React. You can apply one or more CSS classes defined in your stylesheets to the DayPicker component.

Here's the CSS and the component for the same

.calendar-root {
  background-color: #00ffff;
  color: #141414;
  padding: 1rem;
  border-radius: 0.5rem;
}
import "./styles.css";

import React, { useState } from "react";
import { DayPicker } from "react-day-picker";
import "react-day-picker/dist/style.css";

export default function DatePickerWithModifiedClassName() {
  const [selectedDate, setSelectedDate] = useState(new Date());

  return (
    <div>
      <DayPicker
        mode="single"
        classname="calendar-root"
        selected={selectedDate}
        onSelect={setSelectedDate}
      />
    </div>
  );
}

Use classnames to override the default class names of date picker elements

Use this prop when you need to change the default class names — for example, when importing the style via CSS modules or when using a CSS framework.

Here's the CSS and the component for the same:


.calendar-root {
  background-color: #00ffff;
  color: #141414;
  padding: 1rem;
  border-radius: 0.5rem;
}


.day {
  padding: 1rem;
  border: 1px solid pink;
  background-color: #cecece;
}
import "./styles.css";

import React, { useState } from "react";
import { DayPicker } from "react-day-picker";
import "react-day-picker/dist/style.css";

export default function DatePickerWithModifiedClassNames() {
  const [selectedDate, setSelectedDate] = useState(new Date());

  return (
    <div>
      <DayPicker
        mode="single"
        classNames={{ root: "calendar-root", day: "day" }}
        selected={selectedDate}
        onSelect={setSelectedDate}
      />
    </div>
  );
}

You can find a list of all classnames used to override styles of UI, selection states, and day flags on their respective documentation pages.

Use style to add inline styles to the root

The style prop allows you to apply inline styles directly to the DayPicker component. This works like the standard style prop in React, where you pass a JavaScript object containing CSS properties and values.

A few things to remember while using the style prop:

  • Inline styles have the highest specificity and will override styles from CSS files. While convenient for quick, component-specific styling, overuse of inline styles can make your code harder to maintain and can lead to a lack of consistency across your application.

  • Generally, it's recommended to use CSS classes for most styling needs and reserve inline styles for dynamic styles based on component state or props, or for very specific, isolated styling.

export default function StyledDatePickerWithInlineStyle() {
  const [selectedDate, setSelectedDate] = useState(undefined);

  const customStyle = {
    border: '2px solid #00c853',
    borderRadius: '8px',
    padding: '15px',
    fontFamily: 'monospace',
  };

  return (
    <DayPicker
      mode="single"
      selected={selectedDate}
      onSelect={setSelectedDate}
      style={customStyle}
    />
  );
}

Add inline styles to specific parts with styles

The styles prop that allows you to apply inline styles directly to specific parts (sub-components) of the date picker. This gives you fine-grained control over the appearance of individual elements.

The styles prop accepts an object where the keys correspond to the names of the sub-components you want to style (e.g., caption, head, body, day, navButton, etc.), and the values are style objects.

export default function DatePickerWithModifiedStyles() {
  const [selectedDate, setSelectedDate] = useState(new Date());
  const monthCaptionStyle = {
    borderBottom: "1px solid currentColor",
    paddingBottom: "0.5em",
  };

  return (
    <div>
      <DayPicker
        mode="single"
        selected={selectedDate}
        onSelect={setSelectedDate}
        styles={{
          month_caption: monthCaptionStyle
        }}
      />
    </div>
  );
}

You can find a list of all classnames used to override styles of UI, selection states, and day flags on their respective documentation pages.

Choosing the Right Styling Approach

The best styling approach depends on your project's needs and your preferences:

  • className: Ideal for applying consistent styles defined in your CSS files, especially when working with CSS modules or styled components.

  • classnames: Excellent for managing conditional and dynamic CSS class names, making your styling logic cleaner and more maintainable.

  • style: Use sparingly for highly specific, often dynamic, inline styles on the main DayPicker container. Avoid overusing it for general styling.

  • styles: The most powerful option for applying targeted inline styles to the internal parts of the DayPicker. Use this when you need fine-grained control over the appearance of specific elements without writing complex CSS selectors or relying on !important.

In practice, you might even combine these approaches. For example, you could use className for general layout and theming, and the styles prop for tweaking the appearance of specific elements like the navigation buttons or selected day.

Creating Custom Date Picker Components With React Day Picker

This is the final boss. This shows how powerful and robust the react-day-picker library is. You can provide custom components to render the calendar with react-day-picker.

You can pass the set of components as objects, where every key is a part of the calendar anatomy (like day, day button, footer, month, etc.), and the value is the custom component that you built.

import React from "react";

import { DayButtonProps, DayPicker } from "react-day-picker";

const SelectedDateContext = React.createContext<{
  selected?: Date;
  setSelected?: React.Dispatch<React.SetStateAction<Date | undefined>>;
}>({});

function DayButton(props: DayButtonProps) {
  const { day, modifiers, ...buttonProps } = props;

  const { setSelected } = React.useContext(SelectedDateContext);
  return (
    <button
      {...buttonProps}
      onClick={() => setSelected?.(undefined)}
      onDoubleClick={() => setSelected?.(day.date)}
    />
  );
}

export function CustomDayButton() {
  const [selected, setSelected] = React.useState<Date>();

  return (
    <SelectedDateContext.Provider value={{ selected, setSelected }}>
      <DayPicker
        mode="single"
        selected={selected}
        onSelect={setSelected}
        components={{
          DayButton
        }}
        footer={selected?.toDateString() || "Double click to select a date"}
      />
    </SelectedDateContext.Provider>
  );
}

This is how it'd render on the screen:

There are a lot of components you can override by providing a custom component. You can find a list of all components on the react-cay-picker official documentation. By leveraging these custom components, you can achieve highly specific and unique date picker UIs.

Wrapping Up

There are so many things react-day-picker has to offer. We covered everything that you need to build your own Date Picker component on top of it. You can mix and match the options, styles, and customize them as you want.

I hope you found this article helpful. If you did, feel free to share this within your friends and peers so that they can also learn from this. If you want to connect with me, I am active on Peerlist and Twitter.

If you are looking for a new job or want to share a cool project you built, consider Peerlist! It is a professional network for builders to show & tell!

Until then, happy validating!

Create Profile

or continue with email

By clicking "Create Profile“ you agree to our Code of Conduct, Terms of Service and Privacy Policy.