react-calendar, react-datepicker, react-dates, and react-datetime are all React components designed to handle date and time selection in web applications. However, they serve different architectural needs and maturity levels. react-calendar is a lightweight, dependency-free calendar view often used as a building block. react-datepicker is the most popular all-in-one solution offering a text input with a dropdown calendar. react-dates (by Airbnb) is a highly polished, range-selection focused library that is now deprecated and should be avoided for new projects. react-datetime is an older picker that supports time selection but has seen significantly reduced maintenance activity compared to modern alternatives.
Selecting a date picker library is a common but critical architectural decision in React development. The choice impacts bundle size, accessibility compliance, dependency management, and long-term maintainability. While react-calendar, react-datepicker, react-dates, and react-datetime all solve the problem of date selection, they approach it with vastly different philosophies and current statuses. Let's break down how they differ in real-world engineering scenarios.
The most important factor in this comparison is the lifecycle status of the libraries. Using a deprecated library introduces security risks and technical debt.
react-dates is officially deprecated. The maintainers at Airbnb have archived the repository and advised users to migrate away from it. It relies on older React patterns and requires moment.js, which is itself in maintenance mode.
// react-dates: DO NOT USE in new projects
// This library is archived and no longer receives security updates
import { DateRangePicker } from 'react-dates';
<DateRangePicker
startDate={startDate}
endDate={endDate}
onDatesChange={({ startDate, endDate }) => {/*...*/}}
/>;
react-datetime has significantly slowed development. While not formally archived, it remains tightly coupled with moment.js. Modern React ecosystems are moving toward date-fns or native Intl APIs, making this a risky choice for new greenfield projects.
// react-datetime: High risk for new projects due to Moment.js dependency
import Datetime from 'react-datetime';
import moment from 'moment';
<Datetime value={selectedDate} onChange={setSelectedDate} />
react-datepicker and react-calendar are both actively maintained. They have moved away from heavy reliance on moment.js (or made it optional) and support modern React features like hooks and strict mode.
// react-datepicker: Active maintenance, modern API
import DatePicker from 'react-datepicker';
import { registerLocale } from 'react-datepicker';
<DatePicker selected={startDate} onChange={setStartDate} />
// react-calendar: Active maintenance, zero dependencies
import Calendar from 'react-calendar';
<Calendar onChange={setDate} value={date} />
Understanding whether a library provides a full input widget or just a calendar view is essential for architecture.
react-datepicker and react-datetime are "Input Wrappers." They render a text input field and manage a popover containing the calendar. They handle focus management, click-outside detection, and formatting automatically.
// react-datepicker: Renders input + popover automatically
<DatePicker
showTimeSelect
dateFormat="Pp"
selected={date}
onChange={(date) => setDate(date)}
/>
// react-datetime: Renders input + popover automatically
<Datetime
timeFormat="HH:mm"
value={date}
onChange={setDate}
/>
react-calendar is a "View Only" component. It renders the grid of days but does not include an input field or popover logic. You must build the surrounding UI yourself. This offers maximum flexibility but requires more boilerplate.
// react-calendar: You must build the input and popover logic
const [isOpen, setIsOpen] = useState(false);
const [date, setDate] = useState(new Date());
return (
<div>
<input
value={date.toDateString()}
onClick={() => setIsOpen(!isOpen)}
readOnly
/>
{isOpen && (
<Calendar
onClickOutside={() => setIsOpen(false)}
onChange={setDate}
value={date}
/>
)}
</div>
);
react-dates was also an Input Wrapper but specifically optimized for range selection (Start Date to End Date). Its deprecation leaves a gap for complex range inputs, often forcing developers to combine react-calendar with custom logic.
// react-dates: Specialized range input (Deprecated)
<DateRangePicker
startDateId="start_date"
endDateId="end_date"
// ...props
/>
Handling date ranges (e.g., hotel bookings) is a common requirement where these libraries diverge sharply.
react-dates was the industry standard for ranges, offering sophisticated logic for hover states and blocked dates. Since it is deprecated, you cannot use it safely.
// react-dates: Excellent range logic but unsafe to use
<DateRangePicker
numberOfMonths={2}
isOutsideRange={() => false}
// ...
/>
react-datepicker supports ranges natively in recent versions. It allows selecting a start and end date in one continuous interaction.
// react-datepicker: Built-in range support
<DatePicker
selectsRange
startDate={startDate}
endDate={endDate}
onChange={(update) => {
const [start, end] = update;
setStartDate(start);
setEndDate(end);
}}
isClearable={true}
/>
react-calendar supports ranges via the selectRange prop, but again, you must handle the display logic.
// react-calendar: Range selection logic included, UI is manual
<Calendar
selectRange={true}
onChange={setDateRange} // Returns [start, end]
value={dateRange}
/>
react-datetime does not have built-in range selection. You would need to manage two separate instances and validate the logic manually, which increases the risk of bugs.
// react-datetime: No native range support
// Requires two separate components and manual validation
<Datetime value={startDate} onChange={setStartDate} />
<Datetime value={endDate} onChange={setEndDate} />
Dependency management is a key architectural concern. Heavy dependencies like moment.js can bloat your bundle and slow down build times.
react-datetime and react-dates strictly require moment.js and prop-types. This locks you into a larger bundle size and an older date manipulation paradigm.
// react-datetime / react-dates: Heavy dependency chain
// Requires: moment, prop-types
import moment from 'moment';
react-datepicker originally depended on moment.js but has shifted to make it optional or uses date-fns in newer configurations, allowing for tree-shaking and smaller bundles.
// react-datepicker: Flexible dependencies
// Can work with native Date objects or date-fns
import { format } from 'date-fns';
react-calendar has zero dependencies. It is incredibly lightweight and does not force any date manipulation library on you. You can use native JS Date objects or any library you prefer.
// react-calendar: Zero dependencies
// Pure React, works with native Date objects
const nextMonth = new Date(date);
nextMonth.setMonth(nextMonth.getMonth() + 1);
How easily can you match the component to your design system?
react-calendar provides a clean, semantic class structure but relies on CSS for all styling. It does not use inline styles, making it easy to override with CSS modules or Tailwind.
/* react-calendar: Easy CSS override */
.react-calendar__tile--active {
background: #006ed3;
color: white;
}
react-datepicker uses SCSS and provides a default theme. Customization often requires overriding specific class names or passing custom class names to props.
// react-datepicker: Custom class names
<DatePicker
className="custom-input"
calendarClassName="custom-calendar"
dayClassName={(date) =>
date.getDay() === 0 ? 'sunday-highlight' : undefined
}
/>
react-dates used a unique CSS-in-JS approach (via aphrodite) which made overriding styles difficult without ejecting or deeply nesting selectors. This was a common pain point for developers.
// react-dates: Difficult styling due to CSS-in-JS internals
// Required complex theme overrides
You need a simple date field for a user's birthdate in a registration form.
react-datepicker<DatePicker
selected={birthdate}
onChange={(date) => setBirthdate(date)}
dateFormat="MM/dd/yyyy"
/>
You are building an admin dashboard where users click days to view analytics, not to set a form value.
react-calendarreact-calendar is lightweight and dependency-free.<Calendar
onClickDay={(value) => loadAnalytics(value)}
tileClassName={({ date }) =>
hasEvent(date) ? 'event-day' : null
}
/>
Users need to select a check-in and check-out date with visual feedback for the range.
react-datepicker (with selectsRange)react-dates is deprecated. react-datepicker now handles ranges well without the baggage of Moment.js.<DatePicker
selectsRange
startDate={checkIn}
endDate={checkOut}
onChange={(dates) => {
const [start, end] = dates;
setCheckIn(start);
setCheckOut(end);
}}
/>
You are maintaining an old internal tool that already uses moment.js extensively and needs time selection.
react-datetime (only if migration is impossible)moment logic, though migration to react-datepicker + date-fns should be planned.<Datetime
value={meetingTime}
onChange={(val) => setMeetingTime(val)}
timeFormat="HH:mm"
/>
| Feature | react-calendar | react-datepicker | react-dates | react-datetime |
|---|---|---|---|---|
| Status | β Active | β Active | β Deprecated | β οΈ Low Activity |
| Type | View Only | Input + Popover | Input + Popover | Input + Popover |
| Range Support | Yes (Manual UI) | Yes (Native) | Yes (Native) | No (Manual) |
| Dependencies | None | Optional (date-fns) | Moment.js | Moment.js |
| Time Selection | No | Yes | No | Yes |
| Styling | CSS Classes | SCSS / Classes | CSS-in-JS | CSS Classes |
For new projects, react-datepicker is the most balanced choice. It offers a complete input experience, supports ranges, and has an active community maintaining it against modern React standards.
If you need a custom UI or just a calendar grid without the input chrome, react-calendar is superior due to its zero-dependency architecture and flexibility.
Avoid react-dates entirely; its deprecation makes it a liability. Similarly, avoid react-datetime unless you are stuck in a legacy moment.js environment. The industry has moved toward native Date objects and lighter libraries like date-fns, and your date picker choice should reflect that shift.
Choose react-datepicker for standard form inputs where users need to pick a single date, a date range, or include time selection via a dropdown. It is the safest bet for most general-purpose applications due to its active maintenance, extensive configuration options, and lack of heavy external dependencies like Moment.js.
Choose react-calendar if you need a standalone calendar view without an associated text input, or if you want to build a custom date picker wrapper from scratch. It is ideal for dashboards, booking interfaces, or scenarios where you need full control over the input mechanism while relying on a robust, dependency-free calendar engine.
Do NOT choose react-dates for any new project. It has been officially deprecated by its maintainers (Airbnb) in favor of react-dates's successor or other modern solutions. It relies on older patterns and lacks the long-term support required for production environments. Evaluate react-datepicker or react-range-calendar instead.
Choose react-datetime only if you are maintaining a legacy application that already depends on it and specifically requires its Moment.js-based time picking interface. For new developments, avoid this package due to its reliance on the deprecated Moment.js ecosystem and slower update cadence compared to react-datepicker.
A simple and reusable Datepicker component for React (Demo)

The package can be installed via npm:
npm install react-datepicker --save
Or via yarn:
yarn add react-datepicker
Youβll need to install React and PropTypes separately since those dependencies arenβt included in the package. If you need to use a locale other than the default en-US, you'll also need to import that into your project from date-fns (see Localization section below). Below is a simple example of how to use the Datepicker in a React view. You will also need to require the CSS file from this package (or provide your own). The example below shows how to include the CSS from this package if your build system supports requiring CSS files (Webpack is one that does).
import React, { useState } from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
// CSS Modules, react-datepicker-cssmodules.css
// import 'react-datepicker/dist/react-datepicker-cssmodules.css';
const Example = () => {
const [startDate, setStartDate] = useState(new Date());
return <DatePicker selected={startDate} onChange={(date) => setStartDate(date)} />;
};
The most basic use of the DatePicker can be described with:
<DatePicker selected={startdate} onChange={(date) => setStartDate(date)} />
You can use onSelect event handler which fires each time some calendar date has been selected
<DatePicker
selected={date}
onSelect={handleDateSelect} //when day is clicked
onChange={handleDateChange} //only when value has changed
/>
onClickOutside handler may be useful to close datepicker in inline mode
See here for a full list of props that may be passed to the component. Examples are given on the main website.
When using examples from the documentation site, note that they may reference utilities from external libraries. Common imports you might need:
Date manipulation (from date-fns):
import { getYear, getMonth, addDays, subDays, setHours, setMinutes } from "date-fns";
Utility functions:
range() function used in custom headers: import range from "lodash/range";const range = (start, end, step) => Array.from({ length: (end - start) / step }, (_, i) => start + i * step);TypeScript types:
import type { ReactDatePickerCustomHeaderProps } from "react-datepicker";
All examples on the documentation site include commented import statements at the top showing exactly what you need to import for your own project.
For a comprehensive guide on imports, see the Common Imports Guide.
You can also include a time picker by adding the showTimeSelect prop
<DatePicker selected={date} onChange={handleDateChange} showTimeSelect dateFormat="Pp" />
Times will be displayed at 30-minute intervals by default (default configurable via timeIntervals prop)
More examples of how to use the time picker are given on the main website
The date picker relies on date-fns internationalization to localize its display components. By default, the date picker will use the locale globally set, which is English. Provided are 3 helper methods to set the locale:
import { registerLocale, setDefaultLocale } from "react-datepicker";
import { es } from 'date-fns/locale/es';
registerLocale('es', es)
<DatePicker
locale="es"
/>
Locales can be changed in the following way:
setDefaultLocale('es');React-datepicker uses native JavaScript Date objects which are timezone-aware. By default, dates are displayed in the user's local timezone. The library does not include built-in timezone conversion utilities.
Common issue: "Date is one day off" (#1018) - If you're seeing dates shift by one day when converting to ISO strings or sending to a server, this is due to timezone conversion, not a bug. See the Timezone Handling Guide for solutions.
For detailed information about working with timezones, UTC dates, and common timezone-related scenarios, see the Timezone Handling Guide.
For applications requiring timezone conversion, we recommend using date-fns-tz alongside react-datepicker.
We're always trying to stay compatible with the latest version of React. We can't support all older versions of React.
Latest compatible versions:
Up until version 1.8.0, this package was using Moment.js. Starting v2.0.0, we switched to using date-fns, which uses native Date objects, to reduce the size of the package. If you're switching from 1.8.0 to 2.0.0 or higher, please see the updated example above of check out the examples site for up to date examples.
The date picker is compatible with the latest versions of Chrome, Firefox, and IE10+.
Unfortunately, it is difficult to support legacy browsers while maintaining our ability to develop new features in the future. For IE9 support, it is known that the classlist polyfill is needed, but this may change or break at any point in the future.
The main branch contains the latest version of the Datepicker component.
To begin local development:
yarn install from project rootyarn build from project rootyarn start from project rootThe last step starts documentation app as a simple webserver on http://localhost:5173.
You can run yarn test to execute the test suite and linters. To help you develop the component weβve set up some tests that cover the basic functionality (can be found in /tests). Even though weβre big fans of testing, this only covers a small piece of the component. We highly recommend you add tests when youβre adding new functionality.
Please refer to CONTRIBUTING.md file for more details about getting set up.
The examples are hosted within the docs folder and are ran in the simple app that loads the Datepicker. To extend the examples with a new example, you can simply duplicate one of the existing examples and change the unique properties of your example.
Copyright (c) 2014-2025 HackerOne Inc. and individual contributors. Licensed under MIT license, see LICENSE for the full license.