How to create a calendar from scratch in React
Recently, I started working on a project that required a calendar interface. After looking around, I couldn’t really find any small-scale plugins that fit my needs, so I decided to create my own, and share how I did it with anyone in the future who would need something similar.
Before diving in, I’m assuming you have experience with JavaScript and introductory experience with React. Following along also requires that you have NodeJS installed in order to run the npx create-react-app
command. If you don’t already have NodeJS, you can install it here.
Now, let’s get to it.
First, create a react application locally to start developing:
npx create-react-app calendar
Now that you’ve got a react app created, open up your project in your code editor, and create a new file inside of the /src
directory named calendar.js. Inside of this new JavaScript file, create a new Class based component named Calendar:
With the calendar component created, now comes the difficult part: building an entire calendar from scratch. When I started building this, I thought it was best to separate out the functionality into smaller, accomplish-able chunks. For me, the first chunk was getting the current day, a full list of 12 months, and a list of weekdays. So, let’s do this in your calendar component:
Now, you’ve added weekdays, all 12 months, and the current day (through state) in your component. Additionally, you have an <h2>
element that will show the current month and year in a string: February 2021.
So what’s next? For me, the next achievable chunk was laying out the HTML of the calendar. When you think of a calendar in your head, it usually has two main parts: a header (current month/day and tools for changing days), and a table that contains each individual day of the month. With that in mind, let’s lay out the initial HTML:
Now, you have a calendar header (which will have tools for changing days added later) and a calendar body — complete with it’s own header for weekdays, and an empty table that will house the days of the calendar. With the initial HTML done, we can get to the most fun chunk of this project: generating the calendar days!
First, you need to create a new functional component that will house all of the days of the month: calendar-days
. Back inside of the /src
directory, create a new file named calendar-days.js. Inside of it, setup some initial properties:
Now, you have a functional component, that’s going to take in props
from the parent component, Calendar. The props
that you pass in (eventually) will be the current day, and an onClick()
handler.
In order to generate the days of the calendar, you need a few values here: the first day of the month, the weekday of that day, and an initial empty array that we’re going to push each day of the calendar into. We’ll use all of these variables when we loop through the current month to create a calendar. Without further ado, let’s go ahead and do that in our component, right below where you define currentDays:
There’s a lot going on here, so let’s break it down. First up, the loop of 42 days — if you think back to a calendar in your head, a calendar is usually made up of 5-6 weeks, 7 days each. So, 42 blocks are needed in the calendar.
But why do we need 6 weeks? Why not just show 4 or 5 weeks? Good question! Initially, this is what I did. But then I found out there were a lot of months where the first day of the month started on an odd day - so if you only had 4 weeks to show, it wouldn’t actually show the full month. January and February 2021 are great examples of this.
Next up, on the first loop through, you figure out, for the current month, what to set the first day of the calendar to based on what day of the week that first day lies on. (So for February 1, 2021, the weekday is Monday, and the calendar always starts on Sunday, so the first day of the calendar will actually be January 31).
Then, for each day of the calendar, you set up a calendarDay object (with properties for css classes that you’ll use later and onClick event), and push that calendarDay to current days. Now that you have your currentDays array, you can map over it inside of the return statement below:
Here, if all of those ternary statements return true, our final HTML element (repeated 42 times) will look like this:
<div class="calendar-day current selected></div>
Now, back in the parent component, calendar.js, you need to render CalendarDays, and add a new function, changeCurrentDays, to pass down to it through props. Your final Calendar component will look like this:
And that’s it! You have a class component, Calendar, rendering a functional component, CalendarDays, that will update currentDay every time a day is clicked on. If you started up your project locally right now with npm start
, it wouldn’t look like a calendar - it would only be a couple of header tags, and a long list of numbers for the current days of the month.
But, that is easily fixable with some css and flexbox. Create a new file inside of the /src
directory named calendar.css
. Back inside of calendar.js
, import it into the top of the file like this:
Now, add some styles to your calendar components:
Now, if you refresh your app, you should have something that looks like this!
If you’d like to see the full source code for this project (with a small toolbar added), you can check out the Github repo here. Additionally, if you want to check out a live demo of the project (hosted through Github pages), you can visit the demo here.