mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmWeb Frontendupdated 22 Sept 2026

react-datepicker review

react-datepicker 9.1.0 is a controlled React input and popover calendar built on native Date values and date-fns 4. It covers one date, ranges, multiple dates, time lists, month and year views, locale registration, blocked dates, portals, custom inputs, and keyboard navigation. The 9.1.0 release restores non-strict date parsing lost in version 8, fixes default styles and several portal and Safari failures, improves prop types, and lets onClickOutside keep the calendar open through preventDefault(). Our browser build was 190 KB minified and 49.6 KB gzipped, so this is a substantial UI component rather than a small date helper.

Verdict

react-datepicker 9.1.0 installed in 3.6 seconds, used 42 MB across 12 packages, bundled to 49.6 KB gzipped, and produced 0 audit findings in our sandbox. It fits React forms that want a styled Date-based picker with many modes; skip it for strict date-only models, headless design systems, or routes where 190 KB minified is too much.

We installed it

Lab card: what happened when we installed react-datepickerScreenshot of react-datepicker documentation
Install✓ · 3.6s12 packages on disk · 42 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser49.6 KBgzipped (190 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does react-datepicker install cleanly?

Yes. In a fresh container with an empty cache, npm install react-datepicker finished in 4 seconds, leaving 12 packages and 42 MB on disk. npm audit reported no known vulnerabilities.

How much does react-datepicker add to a browser bundle?

49.6 KB gzipped (190 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does react-datepicker work with both ESM and CommonJS?

Yes. Both import 'react-datepicker' and require('react-datepicker') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does react-datepicker include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

react-datepicker or react-day-picker: which should you use?

react-day-picker: Use it when the design system should own the field, popover, markup, and visual treatment around a calendar primitive. react-datepicker 9.1.0 installed in 3.6 seconds, used 42 MB across 12 packages, bundled to 49.6 KB gzipped, and produced 0 audit findings in our sandbox.

When should you not use react-datepicker?

Birthdays or billing dates are stored as YYYY-MM-DD. The component returns Date objects, and the timezone guide documents day shifts caused by careless UTC serialization.

API stability4/5Version 9.1.0 retains the long-running selected and onChange contract, and its declarations separately type single, range, and multiple selection. CommonJS and ESM entry points share an exports map, while React support covers 16.9 through 19. The prop surface is large enough for regressions: version 9.1 restores parsing behavior lost in version 8, and current declarations still expose a misspelled legacy class prop as never.
Docs4/5The README documents CSS setup, control flow, time selection, locale registration, browser expectations, keyboard commands, and links to a full prop reference and live examples. Separate import and timezone guides cover common integration errors. The timezone guide contradicts itself by documenting a working timeZone prop near the top and later saying conversion is not built in, so version 9.1 types and source must settle that question.
Maintenance4/5Version 9.1.0 shipped on December 19, 2025, and GitHub records a push on April 2, 2026. The repository is unarchived, has 8,384 stars, and reports 95 open issues and pull requests. The latest release fixes parsing, default CSS, Lightning CSS, Safari translation, portal markup, masked-input clearing, and prop types. That active repair work is useful, while the broad behavior matrix still demands upgrade testing.
Ecosystem5/5npm counted 5,220,913 downloads from August 18 through August 24, 2026. The component supports React 16.9 through 19, uses date-fns 4 locale objects, optionally works with date-fns-tz 3, and ships CommonJS, ESM, CSS, and TypeScript declarations. It has many examples for form patterns. Teams already committed to Material UI or a headless component system may get a closer fit from that system's own picker.

Use it if

  • A React form needs a ready-styled calendar with single, range, multiple-date, and time selection modes.
  • Application state already uses JavaScript Date objects and the team understands how those values cross timezones.
  • One component should handle locale registration, date limits, custom inputs, inline rendering, and portals.
  • The product can accept a 49.6 KB gzipped measured bundle for the picker and its imported code.
Skip it if

Setup reality

We installed react-datepicker 9.1.0 in a fresh Node 22 Bookworm container. npm completed in 3.6 seconds, left 12 packages, and used 42 MB on disk. npm audit found 0 vulnerabilities at all severity levels. The package declares 3 direct and 3 peer dependencies, is 4676 KB unpacked, and includes TypeScript declarations. Our browser import measured 190 KB minified and 49.6 KB gzipped.

React and react-dom must satisfy the declared 16.9 through 19 range. Import react-datepicker/dist/react-datepicker.css once unless your application replaces the supplied styling. The component is controlled through selected and onChange. Single selection returns Date or null, a range returns a 2-item tuple, and multiple selection returns an array or null. Those distinct callback types are encoded in the bundled declarations.

Date values need a storage decision. A local-midnight birthday can move to another calendar day when converted to UTC. Format date-only values as yyyy-MM-dd from local components; use ISO strings for actual moments. The timeZone prop accepts an IANA identifier and requires date-fns-tz 3. Without that peer, the source logs a development warning and falls back to local-time behavior. Locale data must also be imported from date-fns and registered by name.

Overflow containers can clip the floating calendar. withPortal and portalId move it, which changes focus, stacking, and test selectors. Custom inputs must forward the injected ref and handlers. Version 9.1.0 lets onClickOutside call preventDefault() to keep the calendar open for portal-based header controls. Date filters execute for rendered days, and time choices default to 30-minute intervals. Test keyboard paths, touch input, labels, and validation messages in the actual form.

Patterns

Control one selected date pick-single-date

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

export function ShipDate() {
  const [value, setValue] = useState<Date | null>(null);
  return (
    <DatePicker
      selected={value}
      onChange={setValue}
      placeholderText="Choose a shipping date"
      isClearable
    />
  );
}

Version 9.1 types single selection as Date or null. Import the CSS once or replace the package styles yourself.

Collect a start and end date pick-date-range

const [period, setPeriod] = useState<[Date | null, Date | null]>([null, null]);
const [startDate, endDate] = period;

<DatePicker
  selectsRange
  startDate={startDate}
  endDate={endDate}
  onChange={setPeriod}
  isClearable
/>

selectsRange changes onChange to a 2-item tuple. A single-date setter has the wrong contract for this mode.

Collect separate dates pick-multiple-dates

const [dates, setDates] = useState<Date[] | null>([]);

<DatePicker
  selectsMultiple
  selectedDates={dates ?? []}
  onChange={setDates}
  formatMultipleDates={(items, formatDate) =>
    items.map(formatDate).join(', ')
  }
/>

selectsMultiple returns Date[] or null and enables formatMultipleDates. It cannot be combined with range selection.

Choose a date and a 15-minute slot pick-date-time

<DatePicker
  selected={appointment}
  onChange={setAppointment}
  showTimeSelect
  timeIntervals={15}
  dateFormat="Pp"
/>

The default interval is 30 minutes. Setting 15 changes the list, while the returned value remains a JavaScript Date.

Display a Spanish calendar register-locale

import DatePicker, { registerLocale } from 'react-datepicker';
import { es } from 'date-fns/locale/es';

registerLocale('es', es);

<DatePicker selected={value} onChange={setValue} locale="es" />

Locale registration is explicit. Passing 'es' without importing and registering the date-fns locale does not load it.

Display New York time set-iana-timezone

<DatePicker
  selected={instant}
  onChange={setInstant}
  showTimeSelect
  timeZone="America/New_York"
  dateFormat="MMMM d, yyyy h:mm aa"
/>

timeZone requires date-fns-tz 3. Without the peer, version 9.1 warns in development and uses local-time behavior.

Store a calendar date safely serialize-date-only

import { format } from 'date-fns';

function saveBirthday(date: Date | null) {
  const value = date ? format(date, 'yyyy-MM-dd') : null;
  submit({ birthday: value });
}

<DatePicker selected={birthday} onChange={saveBirthday} />

toISOString() converts to UTC and can change the calendar day. Format a date-only field from the intended local date.

Bound booking dates limit-selectable-dates

import { addMonths, startOfToday } from 'date-fns';

const first = startOfToday();
<DatePicker
  selected={value}
  onChange={setValue}
  minDate={first}
  maxDate={addMonths(first, 6)}
/>

minDate and maxDate are Date values. Keep their timezone assumptions consistent with selected and timeZone.

Disable weekends and closures block-business-dates

import { isSameDay, isWeekend } from 'date-fns';

const closures = [new Date(2026, 11, 25)];
<DatePicker
  selected={value}
  onChange={setValue}
  filterDate={(day) =>
    !isWeekend(day) && !closures.some((closed) => isSameDay(closed, day))
  }
/>

filterDate runs while days render. Large rule sets should use memoized lookup data or the exclusion props.

Protect a portal header control keep-open-on-outside-click

<DatePicker
  selected={value}
  onChange={setValue}
  onClickOutside={(event) => {
    if (headerPortal.current?.contains(event.target as Node)) {
      event.preventDefault();
    }
  }}
/>

Version 9.1 checks defaultPrevented after onClickOutside. Calling preventDefault() keeps the calendar open.

Use a button as the input forward-custom-input

const DateButton = forwardRef<HTMLButtonElement, any>(
  ({ value, onClick, ...inputProps }, ref) => (
    <button ref={ref} type="button" onClick={onClick} {...inputProps}>
      {value || 'Choose date'}
    </button>
  )
);

<DatePicker selected={value} onChange={setValue} customInput={<DateButton />} />

The custom element must forward its ref, click handler, value, and accessibility props or focus and keyboard opening can fail.

Escape an overflow container render-with-portal

<DatePicker
  selected={value}
  onChange={setValue}
  withPortal
  portalId="booking-date-portal"
/>

withPortal moves the calendar in the DOM. Recheck focus order, modal stacking, click-away behavior, and test selectors.

Alternatives

PackageRegistryPick it when
react-day-pickernpmUse it when the design system should own the field, popover, markup, and visual treatment around a calendar primitive.
@mui/x-date-pickersnpmUse it in Material UI applications that need matching fields, adapters, validation, and theme tokens.
flatpickrnpmUse it on framework-neutral pages or mixed frontend stacks where a React-only controlled component is a poor fit.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.