How to Create a React Native Calendar Component

by:

Web Development

React Native is a cross-platform mobile app development framework with a gentle learning curve and lots of built-in components. Because it has a very active developer community, there are also hundreds of open-source third-party component libraries available for it, allowing you to create both Android and iOS apps focusing only on the apps’ core logic. Nevertheless, being able to quickly create your own custom, reusable components from scratch is still an important skill to have.

In this tutorial, I’ll show you how to create a custom React Native Calendar component using just ES6 and a few basic components offered by the framework itself.

1. Creating a New Project

To avoid installing the React Native CLI and all its dependencies on your computer, for now, I suggest you use Expo’s Snack, a free, browser-based IDE for React Native app development. If you don’t have an Expo account already, create one now.

After you’ve logged in to Expo, create a new Snack project by switching to the Snacks tab and clicking on the Create a Snack link.

The IDE will take just a few seconds to create your project and prepare a preview device for it. Once it’s ready, it should look like this:

To keep things simple, all of our code will go inside the App.js file. Before you proceed, make sure you delete all the sample code present in App.js, including the imports.

2. Creating a New Component

To be able to use the React framework and React Native components in your project, add the following import statements at the beginning of the App.js file:

You create a custom React component by creating a class that extends the Component class. Inside the class, you must add a method named render(), which returns JSX code. The following code creates a component named MyCalendar:

In the render() method, we’re currently returning an empty View component. It’s going to serve as a container for all the other components of our calendar.

3. Creating Constants

The calendar component needs two string arrays: one to store the names of the months and one to store the names of the days of the week. Include the following code in the MyCalendar class component, just before it’s render() method.

Next, we’ll need an array that stores the number of days each month has. For February, let the number be 28. We’ll write the code to handle leap years later. Add the following just below the months and weekDays array.

4. Initialize a State

To make our calendar component interactive, we must associate a state with it. For now, we’re going to store nothing but a Date object inside the state, initialized to today’s date. To do this, add the following code to the MyCalendar class, just below nDays array.

The state, of course, is mutable. When a user clicks on a different date in the calendar, we’ll be changing the state to use the new date.

5. Generating a Matrix

A matrix with seven rows and seven columns is large enough to represent any month of the year. We’ll use the first row only as a header, storing the names of the days of the week in it. To create and initialize this matrix, include the following generateMatrix() method between state and render() in MyCalendar class.

Before we start adding days to the matrix, we need to determine the day the current month begins. To do so, first get the year and month of the Date object stored in the state. Then create a new Date object using those values and 1, the first day of the month. By calling the getDay() method of this new object, you get the first day of the month. Add the following code to the generateMatrix function:

We can’t directly use the nDays array to determine the number of days the current month has. If the month’s February, we need to manually add an extra day while dealing with leap years. The following code block shows how to achieve this; please add the code to the generateMatrix function:

At this point, we have all the data we need to fill in the rest of the matrix. The following code shows you how to do so using a counter, two for loops, and two simple if conditions – add it to generateMatrix to complete the function body:

Note that you need to explicitly initialize every element of the 7 x 7 matrix. If you forget to do so, the first or last row may have less than seven elements. This can lead to problems while using the map() method to loop through the matrix.

6. Rendering a Month

Back inside the render() method of the MyCalendar class component, we must now render the matrix we created. So call the generateMatrix() method inside it, just above the return() statement.

Next, let’s display the year and the name of the current month by adding a Text component to the currently empty View component. Optionally, you can use the style prop to add styles to the text. The following JSX code should go inside of the empty <RN.View>¬†element in the return statement of MyCalendar class’s render() method.

In the app preview section, the rendered calendar should now show the current month and year. 

We’ll be using a flexbox to render the contents of each row of the matrix. More precisely, for each row, we’ll be using a View component with its flex and flexDirection parameters set to 1 and row respectively. Additionally, to ensure that all items of the row are of the same width, we’ll set the flexbox’s justifyContent parameter to space-around.

Furthermore, to display the individual elements of the matrix, we’ll use Text components again. By modifying the backgroundColor property of the Text components responsible for the first row’s elements, we can make the header stand out. Similarly, if you want to highlight Sundays, use the color property of the Text components responsible for the first column’s elements.

Our calendar should be able to highlight today’s date, or a date the user selects. Therefore, let’s associate a fontWeight property with each Text component. We’ll set it to bold whenever its contents match the date in our state’s activeDate variable.

The following code shows you how to use the map() method as an alternative to for loops while generating a component hierarchy for the contents of the matrix. Add the code in the render method of MyCalendar class, just before the return statement:

To actually render the matrix, you must now include rows in the JSX returned by the render() method. So add the following code below the <RN.Text> component responsible for displaying the year and name of the month:

You may have noticed that we’ve associated an onPress event handler with each <RN.Text> component displaying a date. We’ll use it to update the activeDate variable whenever users click on a date. Of course, remember to ignore <RN.Text> components that are either empty or responsible for the names of the days of the week.

Accordingly, add the following method anywhere in the body of your MyCalendar class:

7. Changing Months

Our calendar component will have two buttons labeled Next and Previous. These buttons, when pressed, should allow users to move from one month to another. As you may have guessed, inside their event handlers, all we need to do is get the activeDate object and increment or decrement its month by 1.

Accordingly, add the following code towards the end of the JSX returned by the render() method of MyCalendar (keep it inside of <RN.View>):

Next, create the changeMonth() method anywhere in the body of the MyCalendar class. Inside it, you must first call the setState() method and then call the setMonth() method to update the activeDate object.

8. Using the Component

If you run your project now, you should see a calendar that looks like this:

As you can see, our React Native calendar component is ready.

If you want to use the calendar component inside of a parent component, say App, just add it to the render() method of your App class like so:

Feel free to grab the full code for the React Native calendar from snack.

Conclusion

You now know how to create and use a custom React Native calendar component without depending on any third-party packages. The component we created today is interactive, extensible, and can be used in any app with minimal changes. Feel free to add more styles and functionality to it.

To learn more about React Native components, refer to the official documentation. And check out some of our other posts about React Native app development!

Leave a Reply

Your email address will not be published. Required fields are marked *