Create Airbnb-Style Date Picker in React
Let’s create the best user experience by ditching text inputs and dropdowns for dates and building a date picker that simplifies picking a date range.
I will be using this package https://www.npmjs.com/package/react-dates
And the first thing we need to do is install it by running the command in the terminal from the root of your react project:
(export PKG=react-dates;npm info "$PKG" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g; s/ *//g' | xargs npm install --save "$PKG")
in Index.js add at the top where imports are:
import 'react-dates/initialize';
And create a new component let’s name it DatePicker.jsx, where we will create the state for our selected dates, display our date range picker and pass the minimum-maximum range to it(this last part is optional). Our component with the state would look something like this:
import React, { useState } from "react";export const DatePicker = () => {const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const [focusedInput, setFocusedInput] = useState(null);return (
<div>
Date Picker to be inserted here </div>
)};
So we will be storing the start date and the end date and since these are 2 variables we will have 2 input fields and focusedInput
is needed to know which input is focused at the moment so we have appropriate styling and calendar open. Adding the component from the package:
<DateRangePicker
startDate={startDate}
startDateId="date_picker_start_date_id"
endDate={endDate}
endDateId="date_picker_end_date_id"
onDatesChange={handleDatesChange}
focusedInput={focusedInput}
onFocusChange={focusedInput => setFocusedInput(focusedInput)}
/>
We have everything from here that needs to be passed except onDatesChange
which is required, let’s declare this method so we can update the dates and store them in our state:
const handleDatesChange = ({ startDate, endDate }) => {
setStartDate(startDate);
setEndDate(endDate);
};
By default, this picker will enable dates starting today and in the future, but if you need to be able to browse date ranges in the past and up to a certain point in future then we can pass minDate
and maxDate
to our Datepicker
component and calculate what dates are enabled based on that:
import React, { useState } from "react";export const DatePicker = ({ minDate, maxDate }) => {const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const [focusedInput, setFocusedInput] = useState(null);const handleDatesChange = ({ startDate, endDate }) => {
setStartDate(startDate);
setEndDate(endDate);
};const isOutsideRange = day =>
day.isAfter(maxDate) || day.isBefore(minDate);return (
<DateRangePicker
startDate={startDate}
startDateId="date_picker_start_date_id"
endDate={endDate}
endDateId="date_picker_end_date_id"
onDatesChange={handleDatesChange}
focusedInput={focusedInput}
onFocusChange={focusedInput => setFocusedInput(focusedInput)}
isOutsideRange={isOutsideRange} />
)};
We added isOutsideRange
which takes day
as a parameter and returns whether or not it should be enabled by checking if it is withing the range.
Our component is ready now! See below:
Only thing we have to do is call our component in our main file(App.js or Index.js). We first import it at the top and than pass arguments:
import { DatePicker } from "../DatePicker";
In terms of passing minDate
and maxDate
, we should note that react-dates uses moment js, so if we create a date in any other format we would have to convert it into moment. Here’s an example of date as a string:
// in App.js or index.js file... rest of the codeconst minDateString = '07-15-2020';
const maxDateString = '07-15-2022;const minDateMoment = moment(minDateString, 'MM-DD-YYYY');
const maxDateMoment = moment(maxDateMoment, 'MM-DD-YYYY');return (
<DatePicker
minDate={minDateMoment}
maxDate={maxDateMoment}
/>);
If you want to build a calendar from scratch, I have a tutorial where I build calendar component in React and TypeScript:
Let’s keep in touch! Please feel out this form :)