How to add a custom calendar event in a native iOS app using React Native

Accessing a device’s calendar in a React Native app can be a bit tricky. Using open source modules like react-native-add-calendar-event is helpful when you’re looking to show a calendar inside a modal or manipulate calendar events (adding, editing, etc).

In this tutorial, you’re going to cover how to integrate an open source module (react-native-add-calendar-event) in a React Native app to create a custom calendar event add it to the device’s native calendar app.

Here’s a look at what you’re going to build:

Prerequisites

Before you begin this tutorial, you’re going to need the following:

  • Node.js version above 12.x.x installed on your local machine
  • watchman installed
  • Access to one package manager such as npm or yarn
  • React Native version 0.61.x or above
  • An iOS or Android device or simulator

For demonstration purposes, this tutorial covers iOS development.

Create a new React Native app

Start by creating a new React Native app. After the project directory is generated, make sure to navigate inside it through a terminal and run the following commands to install Cocoapods for iOS development:

npx react-native init rncalendareventexample

# after the project directory is created

cd rncalendareventexample

# make sure you have npx installed
npx pod-install

After the dependencies have been installed, run the app on a simulator. To do this, you’ll have to build it for the appropriate mobile OS:

# for iOS
react-native run-ios

# for Android
react-native run-android

Installing react-native-add-calendar-event

Next, you’ll need to add the following dependencies to your React Native project. You’re going to install two libraries right now:

  • react-native-add-calendar-event to add the calendar event to the native app
  • moment to format the date and time

Open up a terminal window and execute the below command:

yarn add react-native-add-calendar-event moment

For iOS developers, make sure you install Cocoapods for react-native-add-calendar-event. Run the following command from a terminal window:

npx pod-install

Add the permissions for the module to work on iOS devices. Add the keys NSCalendarsUsageDescription and NSContactsUsageDescription inside the file ./ios/rncalendarexample_16754/Info.plist, as shown below:

<dict>
<!-- rest of the file remains same -->
<key>NSCalendarsUsageDescription</key>
  <!-- this is a custom message that you can modify the display -->
  <string>Are you sure you want to allow this app to use Calendar?</string>
  <key>NSContactsUsageDescription</key>
  <string></string>
</dict>

Make sure to build the app again before running it:

# for iOS
react-native run-ios

Now you’re good to work on the core elements of the app.

Building the user interface

In this section, let’s build the user interface for the app. Start by importing the necessary statements from different open source libraries used to build this app in App.js. Also, be sure to import the necessary core components from the react-native library:

import React, { useState } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity
} from 'react-native';
import * as AddCalendarEvent from 'react-native-add-calendar-event';
import moment from 'moment';

Next, define a constant that will display the current date and time in UTC mode. Let’s provide a static value for the current date and time for the calendar event, but you can use other modules like @react-native-community/datetimepicker to provide dynamic date and time values.

const TIME_NOW_IN_UTC = moment.utc();

Then, define a state variable inside the functional component App that will let the user add a custom value for the event name. If the user doesn’t add a custom value for the event name, let’s also pass a default name for the event. This is done by using a useState React hook:

export default function App() {
  const [eventTitle, setEventTitle] = useState('Default event');

  // rest of the code
}

The UI for this demo app is going to contain a title, an input field for the user to enter the name of the calendar event, a date and time string to display the current formatted timestamp, and a button to add the calendar event to the device’s calendar app. The input field is going to set the name of the calendar event to the default name of the event passed using the useState hook.

Here’s the complete code for the App function so far:

export default function App() {
  const [eventTitle, setEventTitle] = useState('Default event');

  return (
    <View style={styles.container}>
      <Text style={styles.title}>
        Add Event in device's Calendar from React Native App
      </Text>
      <View style={styles.inputContainer}>
        <Text style={styles.text}>Enter the Event title:</Text>
        <TextInput
          style={styles.input}
          value={eventTitle}
          onChangeText={text => setEventTitle(text)}
        />
        <Text style={styles.text}>Current Date and Time of the event:</Text>
        <Text style={styles.text}>
          {moment
            .utc(TIME_NOW_IN_UTC)
            .local()
            .format('lll')}
        </Text>
      </View>
      <TouchableOpacity style={styles.button}>
        <Text style={[styles.text, { color: 'white' }]}>
          Add this event to the calendar
        </Text>
      </TouchableOpacity>
    </View>
  );
}

The corresponding style references are created using a StyleSheet object:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#f8f8f2',
    paddingTop: 60
  },
  title: {
    fontSize: 20,
    textAlign: 'center'
  },
  inputContainer: {
    marginVertical: 20
  },
  text: {
    fontSize: 16,
    color: '#000',
    marginVertical: 5
  },
  input: {
    fontSize: 14,
    marginVertical: 10,
    padding: 5,
    backgroundColor: '#ebebeb',
    borderColor: '#333',
    borderRadius: 4,
    borderWidth: 1,
    textAlign: 'center'
  },
  button: {
    alignItems: 'center',
    backgroundColor: 'purple',
    padding: 10,
    marginTop: 10,
    borderRadius: 10
  }
});

If you go back to the simulator, you’re going to get the following result:

Creating a calendar event and handling the dialog

So far you’ve built the core UI. In this section, let’s add the functionality to access the device’s calendar and add a calendar event in real-time using the React Native app.

react-native-add-calendar-event module provides a function called AddCalendarEvent that’s promise-based. Through this promise, you can add a new event directly to the calendar app for the mobile platform you’re using.

Using one of the methods of this promise-based function called AddCalendarEvent.presentEventCreatingDialog, you can simply access an editable calendar event directly in our React Native app in the form of a dialog box. However, this method accepts one argument and is an eventConfig object.

This object needs the title of the event, the starting date string of the event, the end date string of the event, and, optionally, you can add a default description in the form of notes.

To provide a date string to this config object, you need to first convert the current date into a string format. For that, add the below helper method before the App component in App.js:

const utcDateToString = momentInUTC => {
  let s = moment.utc(momentInUTC).format('YYYY-MM-DDTHH:mm:ss.SSS[Z]');
  return s;
};

This method takes one input, the UTC date stamp, and uses the moment.js library to convert it to the desirable string format required by the calendar app.

Go inside the App component and add a helper method called addEventToCalendar.

This method accepts two arguments: the name of the event and the date string. Inside this method, you’re also going to configure the eventConfig object and pass it as the argument for the promise-based method AddCalendarEvent.presentEventCreatingDialog().

function addEventToCalendar(title, startDateUTC) {
  const eventConfig = {
    title: eventTitle,
    startDate: utcDateToString(startDateUTC),
    endDate: utcDateToString(moment.utc(startDateUTC).add(1, 'hours')),
    notes: 'Default Event Description'
  };

  AddCalendarEvent.presentEventCreatingDialog(eventConfig)
    .then(eventInfo => {
      alert(JSON.stringify(eventInfo));
    })
    .catch(error => {
      alert('Error ', error);
    });
}

The promise handles whether the event is created or if the user has canceled the process of creating the event. This is done using eventInfo, which returns an eventId. You can store this event ID in a state variable and add further functionality, such as editing an existing event in the calendar app (think of this as the challenge of this post).

Lastly, make sure to add this helper method as the value of onPress on the TouchableOpacity button component in App.js, where you’re returning JSX:

<TouchableOpacity style={styles.button} onPress={addEventToCalendar}>
  <Text style={[styles.text, { color: 'white' }]}>
    Add this event to the calendar
  </Text>
</TouchableOpacity>

Now go back to the simulator and try to add a new event. Here’s a demo of the app you’ve built so far that actually stores the calendar event in the calendar app of an iOS device:

You’ll notice that the event id is returned by the promise. In the case of canceling the process of creating a new event, you get a new action from the promise called CANCELLED, as shown below:

And that’s it! You can see above that the event has been successfully stored in the native iOS calendar app.

Conclusion

The react-native-add-calendar-event package is great. It allows you to add custom events from a React Native app to a device’s native calendar app. Generally this type of feature or functionality is used in hotel rental and flight booking apps, to name just a couple potential use cases.

To explore more, I’d suggest you take a look at the following resource:

👉 To learn more about React Native, check out these resources:

Fritz

Our team has been at the forefront of Artificial Intelligence and Machine Learning research for more than 15 years and we're using our collective intelligence to help others learn, understand and grow using these new technologies in ethical and sustainable ways.

Comments 0 Responses

Leave a Reply

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

wix banner square