Making a Calendar in React

Harriet Bicknell
Analytics Vidhya
Published in
4 min readApr 15, 2020

In my final project at Flatiron, I wanted to make a booking system similar to Airbnb which would allow users to select a range of dates on a calendar and see the dates that have been blocked out. After hours of searching multiple practice attempts, I found the perfect mobile-friendly datepicker library which coincidentally is called react-dates from Airbnb. This blog is going to be a tutorial about how to set up the calendar in your applications, block out dates and grab date-ranges.

  1. Getting it set up

First of all make sure that you have correct dependencies installed. For this demo, I am going to be using bootstrap, react-dates, moment and moment-range.

npm install --save bootstrap react-dates moment moment-range

Then go to src>App.js and make sure you have the following imports:

import React, {Component} from ‘react’;
import ‘bootstrap/dist/css/bootstrap.min.css’;
import ‘react-dates/initialize’;
import ‘react-dates/lib/css/_datepicker.css’;
import {DateRangePicker} from ‘react-dates’;
import Moment from "moment";
import { extendMoment } from "moment-range";
import ‘./App.css’;

Once this is done, copy the following code into App.js:

class App extends Component {
state = {
startDate: null,
endDate: null
};
render() {
return (
<div className='App'>
<DateRangePicker
startDate={this.state.startDate}
startDateId="your_unique_start_date_id"
endDate={this.state.endDate}
endDateId="your_unique_end_date_id"
onDatesChange={({ startDate, endDate }) => this.setState({ startDate, endDate })}
focusedInput={this.state.focusedInput}
onFocusChange={focusedInput => this.setState({ focusedInput })}
/>
</div>
);
}
}
export default App;

At this point, you should already be able to see the calendar when you run npm install! It is that simple! But I'm guessing that like me, you also want to be able to do something with that calendar. If you have a look at the documentation for react-dates (which I have linked below) you will see that there are lots of props you can provide the DateRangePicker. You can explore the storybook to see all of these but I am specifically going to tackle how I went about blocking dates and grabbing dates in the next couple of sections.

2. Blocking out dates

React-date kindly provides us with a prop that lets you pass a function and it will block out dates accordingly — isDayBlocked. After some detective work (aka console-logging) I discovered that the function that the isDayBlocked prop gives the function one date at a time and return true or false when it comes out of the function. If the return value is true then the day will be blocked. Sounds simple right?! But no. For my application, I needed to store a startDate and an endDate in my database. I realised that I needed to create a range for all of the dates in between to also be blocked out. This part requires you to delve into the world of moment.js which is a little intimidating but actually quite simple once you read the documentation. After a lot of thinking and writing everything out step by step, I came up with this solution:

isBlocked = date => {
let bookedRanges = [];
let blocked;
bookings.map(booking => {
bookedRanges = [...bookedRanges,
moment.range(booking.startDate, booking.endDate)]
}
);
blocked = bookedRanges.find(range => range.contains(date));return blocked;
};

First, I transform my array of bookings into an array of ranges using moment.range( ). This requires a startDate and an endDate. Then I take that array and for every date that gets passed in by the DateRangePicker, I use .find( ) to check if it is in my range. If it is then it will give me a true or false value which is given back to the DateRangePicker.

3. Grabbing the dates

Next stop for my booking Calendar was to be able to select the dates in order to create a booking. To make things easier, I have made an example using an alert with startDate and endDate to test that the right values are being returned. As you can see above(and below), startDate and endDate need to have their own state. This is very advantageous for use because it means it is very easy to grab that data. I made a button to make an alert for both of these pieces of state onClick to allow myself to see that the state was updating accordingly. This gave me everything I needed in order to make my actual booking method.

This is what my App.js file now looks like with all of the code:

class App extends Component {
state = {
startDate: null,
endDate: null
};
alertStartDate = () => {alert(this.state.startDate)}; alertEndDate = () => {alert(this.state.endDate)}; render() {
return (
<div className='App'>
<DateRangePicker
startDate={this.state.startDate}
startDateId="your_unique_start_date_id"
endDate={this.state.endDate}
endDateId="your_unique_end_date_id"
onDatesChange={({ startDate, endDate }) => this.setState({ startDate, endDate })}
focusedInput={this.state.focusedInput}
onFocusChange={focusedInput => this.setState({ focusedInput })}
isDayBlocked={this.isBlocked}
/>
<button onClick={this.alertStartDate}>Click me for start date</button> <button onClick={this.alertEndDate}>Click me for end date</button> </div>
);
}
}
export default App;

This was the component of my final project that I was most nervous about getting started on. But I was reminded yet again that if I breaks things down into tiny pieces, I will eventually find the solution. Even if you application doesn’t require this exact functionality, I hope this article as useful demonstration for how to use get the react-dates calendar set up and where to go from there.

Sources:

http://airbnb.io/react-dates/?path=/story/drp-input-props--default

--

--