Date pickers are the form control that looks done after a day and keeps coming back as tickets. It works on your iPhone, but on a Samsung in Berlin the week starts on the wrong day. The birthday field defaults to today, so users scroll back forty years one month at a time. The hotel booking needs a range, and the native picker cannot do ranges. Then the date the user picked arrives on the server one day earlier, because someone called toISOString() on midnight local time.
This is a practical comparison of the React Native date picker options that are worth using in late 2026, checked on npm on October 12. It covers code for the ones I would ship, the time zone bug everyone hits, and a decision table at the end.
Native picker or calendar component?
Like dropdowns, date pickers come in two kinds, and deciding which one you need first saves you from most of the bad picks:
- A native picker uses the OS control:
UIDatePickeror the SwiftUIDatePickeron iOS, a Material dialog on Android. You pick one date, one time, or both. It is accessible, localized and familiar, and you get almost no control over how it looks. - A calendar component is drawn in JavaScript: a month grid that you style yourself. It is the only way to get date ranges, multiple dates, marked or disabled days, and a design that looks the same on both platforms.
If the requirement says “check-in and check-out” or “show which days have bookings”, skip straight to the calendar section. A native picker cannot do it.
The options at a glance
| Library | Kind | Version (Oct 2026) | Last publish | Weekly downloads |
|---|---|---|---|---|
@react-native-community/datetimepicker |
Native | 9.2.1 | Sep 2026 | ~2.76M |
@expo/ui (community/datetime-picker) |
Native (SwiftUI / Compose) | 57.0.22 | Oct 2026 | ~5.2M (whole package) |
react-native-date-picker |
Native-style wheel | 5.0.13 | Jun 2025 | ~298K |
react-native-modal-datetime-picker |
Modal wrapper over community | 18.0.0 | Aug 2024 | ~852K |
react-native-ui-datepicker |
JS calendar | 3.3.0 | May 2026 | ~91K |
react-native-paper-dates |
JS calendar (Material) | 0.24.1 | Oct 2026 | ~49K |
react-native-calendars |
JS calendar views | 1.1314.0 | Jan 2026 | ~500K |
@react-native-community/datetimepicker: the default
This is the package that used to be core’s DatePickerIOS and TimePickerAndroid. It is the one Expo bundles, and it is the one most other libraries wrap. Version 9 changed two things you should know about if you are coming from old tutorials. 9.0.0 (March 2026) removed the deprecated Android positiveButtonLabel, negativeButtonLabel and neutralButtonLabel props in favour of positiveButton and friends. 9.1.0 introduced separate listeners, so onChange is now deprecated in favour of onValueChange, onDismiss and onNeutralButtonPress. The old single onChange that fired with event.type === 'dismissed' still works. It just isn’t how you should write new code.
npx expo install @react-native-community/datetimepicker
# bare React Native
npm install @react-native-community/datetimepicker
Android: use the imperative API
The library’s own README recommends the imperative API on Android, because the Android picker is a dialog and not a view:
import { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { DateTimePickerAndroid } from '@react-native-community/datetimepicker';
export function DueDateField() {
const [date, setDate] = useState(new Date());
const open = () =>
DateTimePickerAndroid.open({
value: date,
mode: 'date',
design: 'material',
minimumDate: new Date(),
onValueChange: (_event, selected) => setDate(selected),
});
return (
<View>
<Button title="Pick a due date" onPress={open} />
<Text>{date.toLocaleDateString()}</Text>
</View>
);
}
design: 'material' gives you the Material 3 picker instead of the older default dialog, and unlocks title, fullscreen and initialInputMode. It needs your Android app theme to inherit from Theme.Material3.DayNight.NoActionBar in styles.xml, otherwise it crashes on open. That is the first thing to check when it “works in the example app”.
iOS and cross-platform: the component
import DateTimePicker from '@react-native-community/datetimepicker';
{show && (
<DateTimePicker
value={date}
mode="date"
display="inline"
minimumDate={new Date(1920, 0, 1)}
maximumDate={new Date()}
onValueChange={(_event, selected) => setDate(selected)}
onDismiss={() => setShow(false)}
/>
)}
On iOS, display controls the look: 'compact' (a small button that expands), 'inline' (the full calendar), or 'spinner' (the classic wheel). For a birthday field the spinner is still the kindest option, because scrolling a year wheel beats paging back through 480 months. mode="datetime" and mode="countdown" exist on iOS only. On Android, pick a date and then a time in two dialogs.
Expo UI’s drop-in DateTimePicker
On Expo SDK 57, @expo/ui ships a DateTimePicker whose API matches the community package. It uses SwiftUI’s DatePicker on iOS and Jetpack Compose on Android, which means Material 3 by default without the theme change. Per the Expo docs, migrating means changing one import:
import DateTimePicker from '@expo/ui/community/datetime-picker';
{show && (
<DateTimePicker
value={date}
mode="date"
presentation="dialog"
onValueChange={(_event, selected) => {
setShow(false);
setDate(selected);
}}
onDismiss={() => setShow(false)}
/>
)}
The differences are listed plainly in the docs. There is no DateTimePickerAndroid.open(); you render the component with presentation="dialog" on Android (iOS ignores the prop and renders inline). countdown mode, minuteInterval, textColor, firstDayOfWeek, the neutral button, fullscreen, title and startOnYearSelection are not supported. Time zones take an IANA timeZoneName rather than timeZoneOffsetInMinutes. If you don’t rely on any of those, on Expo this is the version I would start with. Our dropdown comparison reached the same conclusion about Expo UI’s Picker: the SDK is gradually turning community shims into native components.
react-native-date-picker: the wheel, everywhere
Henning Hall’s react-native-date-picker draws an iOS-style wheel on both platforms, inline or in its own modal, with date, time and datetime modes. That makes it the usual answer when a designer wants the same picker on Android and iOS:
import { useState } from 'react';
import { Button } from 'react-native';
import DatePicker from 'react-native-date-picker';
export function ReminderField() {
const [date, setDate] = useState(new Date());
const [open, setOpen] = useState(false);
return (
<>
<Button title="Set reminder" onPress={() => setOpen(true)} />
<DatePicker
modal
open={open}
date={date}
mode="datetime"
minuteInterval={15}
theme="auto"
onConfirm={(value) => {
setOpen(false);
setDate(value);
}}
onCancel={() => setOpen(false)}
/>
</>
);
}
Two caveats. It has custom native code, so it works in Expo development builds but not in Expo Go (no config plugin needed). And the last npm release, 5.0.13, came out in June 2025. It still works in plenty of apps, but sixteen months without a publish is a risk for a native module, given how often React Native changes the native side. Pin the version and test it on each RN upgrade.
react-native-modal-datetime-picker: check whether you still need it
This wrapper puts the community picker inside a modal with confirm and cancel buttons, giving you an isVisible, onConfirm, onCancel API on both platforms. It still has 850K weekly downloads, mostly from apps that adopted it years ago. Its last release was 18.0.0 in August 2024. Today the community picker’s own display="inline" on iOS, the Android dialog, or the Expo UI component cover the same ground with one less dependency. I would not add it to a new project. If you already use it, there is no hurry to remove it, but don’t build anything new on it.
Calendars: ranges, multiple dates and full styling
react-native-ui-datepicker
A pure JavaScript calendar with single, range and multiple modes, an optional time picker, Gregorian and Jalali calendars, and styling through either a styles object or Tailwind-style classNames (handy with NativeWind). No native code, so it runs in Expo Go and on web:
import { useState } from 'react';
import DateTimePicker, { DateType, useDefaultStyles } from 'react-native-ui-datepicker';
export function StayDates() {
const defaultStyles = useDefaultStyles();
const [range, setRange] = useState<{ startDate: DateType; endDate: DateType }>({
startDate: undefined,
endDate: undefined,
});
return (
<DateTimePicker
mode="range"
startDate={range.startDate}
endDate={range.endDate}
minDate={new Date()}
onChange={({ startDate, endDate }) => setRange({ startDate, endDate })}
styles={defaultStyles}
/>
);
}
It renders inline, so for a pop-up put it inside a sheet. Our bottom sheet guide covers the options, and a plain modal works too.
react-native-paper-dates
If your app already uses React Native Paper, this is the Material Design match: single, range, multiple and input date pickers, plus a time picker with clock face or keyboard input, all in modals styled by your Paper theme. Formatting uses the native Intl APIs, and translations are built in. It is actively maintained (0.24.1 shipped October 10):
import { DatePickerModal } from 'react-native-paper-dates';
<DatePickerModal
locale="en"
mode="range"
visible={open}
onDismiss={() => setOpen(false)}
startDate={range.startDate}
endDate={range.endDate}
onConfirm={({ startDate, endDate }) => {
setOpen(false);
setRange({ startDate, endDate });
}}
/>
react-native-calendars
Wix’s react-native-calendars is less a picker than a calendar display kit: Calendar, CalendarList, Agenda, ExpandableCalendar and markedDates for dots, periods and disabled days. Use it when the calendar is the screen (bookings, schedules, habit trackers) rather than a form field. For a simple range input it is more than you need.
The bug everyone ships: dates off by one
Every picker above gives you a JavaScript Date, which is a point in time, not a calendar day. Pick “March 3” at local midnight in Berlin, call toISOString(), and you send 2027-03-02T23:00:00.000Z. The server stores March 2, and a user files a bug report. The fix is to decide what you are storing:
- A calendar day (birthday, due date, check-in): send
YYYY-MM-DDbuilt from the local parts, and never convert to UTC. - A moment (appointment, reminder): send the full ISO timestamp and the user’s IANA time zone, so you can render it correctly for someone in another zone.
// a calendar day, no UTC conversion
const toDay = (d: Date) =>
`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
// a moment, plus the zone it was chosen in
const payload = {
at: date.toISOString(),
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};
Hermes ships full Intl support now, so toLocaleDateString and Intl.DateTimeFormat work on both platforms without polyfills. For display, use them. For arithmetic across time zones, a library like date-fns with its tz helpers or Temporal (once it lands in your runtime) beats hand-rolled maths.
Four smaller things worth getting right
- Start where the user is likely to be. A birth date picker should open around 30 years ago with
maximumDateset to today. A booking picker should haveminimumDateset to today. - Locale on iOS comes from the project. The community picker follows the languages declared in your Xcode project. Its
localeprop is iOS only and the README itself discourages it outside the spinner display. - Dark mode. On iOS,
themeVariantforces light or dark if your app does not follow the system.react-native-date-pickerhastheme. Calendars follow whatever styles you pass. - Test the dismissal path. On Android, a user tapping outside the dialog fires
onDismiss, notonValueChange. Code that only closes the picker in the value handler leaves your “show” state stuck at true.
Which one should you use?
| You need | Use |
|---|---|
| One date or time, native look, any setup | @react-native-community/datetimepicker |
| One date or time on Expo, Material 3 and SwiftUI by default | @expo/ui/community/datetime-picker |
| The same wheel on iOS and Android | react-native-date-picker (pin it) |
| Date range or multiple dates, custom styling | react-native-ui-datepicker |
| Already on React Native Paper | react-native-paper-dates |
| A calendar screen with marked days and agenda | react-native-calendars |
My default for a new app: the native picker (Expo UI’s drop-in on Expo, the community package otherwise) for every single-date field, and react-native-ui-datepicker inside a sheet the moment someone says “range”. If you only remember one thing from this post, make it the YYYY-MM-DD helper. It prevents more bug reports than the choice of library does. If you are still deciding on Expo itself, our Expo explainer covers what you gain and what you give up.
FAQ
Does React Native have a built-in date picker?
No. The old core DatePickerIOS and DatePickerAndroid were removed. The maintained replacement is @react-native-community/datetimepicker, and Expo also offers a native one in @expo/ui.
What is the best date picker for React Native?
For a single date or time, @react-native-community/datetimepicker, or Expo UI’s DateTimePicker on Expo. For date ranges, use a calendar component like react-native-ui-datepicker or react-native-paper-dates.
How do I pick a date range in React Native?
Native pickers only select one value. Use react-native-ui-datepicker with mode="range", or DatePickerModal from react-native-paper-dates with mode="range".
Why is my selected date one day off?
You converted a local midnight Date to UTC with toISOString(). For calendar days, send a YYYY-MM-DD string built from the local year, month and day instead.
Is onChange deprecated in @react-native-community/datetimepicker?
Yes, since 9.1.0. Use onValueChange for a selected value, onDismiss for a cancelled picker, and onNeutralButtonPress for the Android neutral button. onChange still works for now.
Does react-native-date-picker work with Expo?
Yes, in development builds. It does not work in Expo Go because it contains custom native code.