React Native, Local, Scheduled, Push Notification With Firebase
Tags: reactnative, firebase, pushnotification, localpushnotification
Published: 2019-07-04 13:30:15

---
title: React Native, Local, Scheduled, Push Notification With Firebase
published: true
description: Use firebase to schedule a local push notification
tags: React Native, Firebase, Push Notification, Local Push Notification
cover_image: https://thepracticaldev.s3.amazonaws.com/i/2x602xh5yckjxv43dlkw.jpg
---

With ever going increase in app usage, the app developers try to find new ways to keep their user engaged with their apps. Push notifications are one way to keep your users engaged and informed.

Push notifications are the communications channel used by apps to drive user re-engagement and retention. Push notification technology has come a long way from being a single messages delivery system to a rich and interactive medium.

There are two types of notifications, remote and local notifications.

### Remote Notifications

With remote notifications, you use one of your company’s servers to push data to user devices via the Apple Push Notification service or FCM.

### Local Notifications

Both Android and IOS support the ability to trigger notifications from your application locally. These can either be displayed immediately, or scheduled to be displayed at a later date.

In this article we will be using local notifications feature to send daily a reminder to the user at a particular time every day.

## Prerequisites

This tutorial requires basic knowledge of React Native. To set up your development machine, follow the official guide [here](https://facebook.github.io/react-native/docs/0.59/getting-started).

To implement push notifications in React Native application, we are going to use the [react-native-firebase](https://github.com/invertase/react-native-firebase).

React Native Firebase has Notifications module that supports for both remote (FCM) and local notifications.

To make sure we are on the same page, the following are the versions used in this tutorial:

- Node v10.15.0
- npm 6.4.1
- yarn 1.16.0
- react-native 0.59.9
- react-native-firebase 5.2.3

## Getting Started

To create a new project using `react-native-cli`, type the following in terminal:

```bash
$ react-native init localReminders
```

```bash
$ cd localReminders
```

#### Install React Native Firebase

Install `react-native-firebase` by following installation instructions [here](https://rnfirebase.io/docs/v5.x.x/installation/initial-setup).

Make sure you have completed both iOS and Android setup.

#### Install Modules

React Native Firebase only provides your application with access to Core features.

To user notification in our react native app, we'll need to also install the **Cloud Messaging** and **Notifications** modules.

Install **Cloud Messaging** by following the instructions [here](https://rnfirebase.io/docs/v5.x.x/messaging/ios).

Install **Notifications** by following the instructions [here](https://rnfirebase.io/docs/v5.x.x/notifications/ios).

Again, make sure you followed the steps for both iOS and Android.

## Initial code setup

In your `App.js` file add these imports:

```js
import React, { Component } from "react";
import { Alert } from "react-native";
import firebase from "react-native-firebase";

import Dashboard from "./src/Dashboard";
```

Create an empty `Dashboard.js` file in your `src` folder. We'll fill this with code in later part of the tutorial.

Now create a `class` component called `App` as follow:

```js
export default class App extends Component {
  componentDidMount() {
    // Create notification channel required for Android devices
    this.createNotificationChannel();

    // Ask notification permission and add notification listener
    this.checkPermission();
  }

  createNotificationChannel = () => {};

  checkPermission = async () => {};

  render() {
    return <Dashboard />;
  }
}
```

We've created a few helper methods in this class component that we called on `componentDidMount()` lifecycle method. In render, we'll return the `Dashboard` component.

Let's review and add code to these methods and see what they do and why do we need them.

## Create Android Notification Channel

As of Android 8.0 (API Level 26), notifications must specify a Notification Channel or they will not appear.

To allow React Native Firebase to work seamlessly across all versions of Android, you will need to create a channel before you can display a notification. This block of code can be re-run multiple times, so it is safe to do it each time your application starts.

To create this notification channel we created a custom helper method `createNotificationChannel()`. Update it with the following:

```js
createNotificationChannel = () => {
  // Build a android notification channel
  const channel = new firebase.notifications.Android.Channel(
    "reminder", // channelId
    "Reminders Channel", // channel name
    firebase.notifications.Android.Importance.High // channel importance
  ).setDescription("Used for getting reminder notification"); // channel description

  // Create the android notification channel
  firebase.notifications().android.createChannel(channel);
};
```

Android channel accept three parameters `channelId`, `name` and `importance`.

For full reference documentation, please see [**AndroidChannel**](https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidChannel) and [**AndroidNotifications**](https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidNotifications).

## Notification Permission and Listener

Before we can send any notification we need to make sure we have the notification permission and then, when we have that permission we can add a notification listener. This notification listener will listen for any notification and return us with the `notification` when received.

Update your `checkPermission()` method with the following:

```js
checkPermission = async () => {
  const enabled = await firebase.messaging().hasPermission();
  if (enabled) {
    // We've the permission
    this.notificationListener = firebase
      .notifications()
      .onNotification(async notification => {
        // Display your notification
        await firebase.notifications().displayNotification(notification);
      });
  } else {
    // user doesn't have permission
    try {
      await firebase.messaging().requestPermission();
    } catch (error) {
      Alert.alert(
        "Unable to access the Notification permission. Please enable the Notification Permission from the settings"
      );
    }
  }
};
```

When the notification listener receives a notification, we call `displayNotification()` method with the `notification` received which will display the notification.

We can now receive and show the notification. Now its time to schedule a local notification which will fire at some point in the future.

## Dashboard Screen

We are going to create a **Dashboard** screen which will have a switch to enable and disable notifications and a time picker to set time to receive notifications. It will look something like below.

![](https://thepracticaldev.s3.amazonaws.com/i/cx2mdkb5bpzr7m6uegmo.png)

To make this UI Screen we'll add few third party helper libraries.

1. [react-native-elements](https://react-native-training.github.io/react-native-elements/) - UI component library
2. [moment](https://momentjs.com/) - Handling Date Object
3. [react-native-modal-datetime-picker](https://github.com/mmazzarolo/react-native-modal-datetime-picker) - A React-Native datetime-picker for Android and iOS

Let's start with adding the required imports:

```js
import React, { Component } from "react";
import { Platform, StyleSheet, Text, SafeAreaView, View } from "react-native";
import { ListItem } from "react-native-elements";
import firebase from "react-native-firebase";
import DateTimePicker from "react-native-modal-datetime-picker";
import moment from "moment";
```

Now we'll create and default export `Dashboard` class component.

Now, add some local states:

```js
state = {
  enableNotification: true,
  isDateTimePickerVisible: false,
  notificationTime: moment({ hour: 17 })
};
```

Now we want to set reminder as soon as user lands on the dashboard, so we'll create and call a `setReminder()` method on `componentDidMount()` lifecycle method:

```js
componentDidMount() {
  this.setReminder();
}

setReminder = async () => {
  const { notificationTime, enableNotification } = this.state;

  if (enableNotification) {
    // schedule notification
    firebase.notifications().scheduleNotification(this.buildNotification(), {
      fireDate: notificationTime.valueOf(),
      repeatInterval: 'day',
      exact: true,
    });
  } else {
    return false;
  }
};
```

In `setReminder()` method first we use `notificationTime` and `enableNotification` state.

If `enableNotification` is true we schedule the notification using [`scheduleNotification()`](https://rnfirebase.io/docs/v5.x.x/notifications/reference/Notifications#scheduleNotification) method.

The `scheduleNotification()` has two parameters, `notification` and `schedule`.

For `notification` we'll call another custom method `buildNotification()` which will return notification and, in `schedule` we'll pass an object with `fireDate`, `repeatInterval` and `exact` keys.

The `fireDate` is the date when the notification should first be shown, in milliseconds. For `repeatInterval` we'll use `day`, as we want the notification to be shown everyday. The `exact` option is Android only and it denotes if the `fireDate` should be respected exactly, i.e. for reminders, or if it can deviate slightly to save battery.

In else we'll just return `false`.

Now, we'll add `buildNotification()` method which will build a notification when a notification is received:

```js
buildNotification = () => {
  const title = Platform.OS === "android" ? "Daily Reminder" : "";
  const notification = new firebase.notifications.Notification()
    .setNotificationId("1") // Any random ID
    .setTitle(title) // Title of the notification
    .setBody("This is a notification") // body of notification
    .android.setPriority(firebase.notifications.Android.Priority.High) // set priority in Android
    .android.setChannelId("reminder") // should be the same when creating channel for Android
    .android.setAutoCancel(true); // To remove notification when tapped on it

  return notification;
};
```

Let's add some helper method for the notification `switch` and time picker. These will be used by their respective components to set local states which will then later be used:

```js
enableNotification = value => {
  this.setState({
    enableNotification: value
  });
};

showDateTimePicker = () => {
  this.setState({ isDateTimePickerVisible: true });
};

hideDateTimePicker = () => {
  this.setState({ isDateTimePickerVisible: false });
};

handleDatePicked = date => {
  this.hideDateTimePicker();

  this.setState({
    notificationTime: moment(date)
  });
};
```

Finally, the `render()` which we'll return the UI of the dashboard:

```js
render() {
  const { enableNotification, isDateTimePickerVisible, notificationTime } = this.state;
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.cardTitleView}>
        <Text style={styles.cardTitle}>Add Reminder</Text>
      </View>
      <ListItem
        title="Notification"
        bottomDivider
        titleStyle={styles.titleStyle}
        switch={{ onValueChange: this.enableNotification, value: enableNotification }}
      />
      <ListItem
        title="Time"
        titleStyle={styles.titleStyle}
        onPress={this.showDateTimePicker}
        rightElement={<Text style={{ opacity: 0.7 }}>{moment(notificationTime).format('LT')}</Text>}
      />
      <DateTimePicker
        isVisible={isDateTimePickerVisible}
        onConfirm={this.handleDatePicked}
        onCancel={this.hideDateTimePicker}
        mode="time" // show only time picker
        is24Hour={false}
        date={new Date(notificationTime)}
        titleIOS="Pick your Notification time"
      />
    </SafeAreaView>
  );
}
```

Time to sprinkle in some styles to make UI more appealing.

```js
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#EEEFF0"
  },
  cardTitleView: {
    paddingHorizontal: 15,
    paddingTop: 15,
    paddingBottom: 8
  },
  cardTitle: {
    fontSize: 15,
    color: "#585858",
    fontWeight: "600"
  },
  titleStyle: {
    fontSize: 20,
    color: "#585858"
  }
});
```

That's it. We are done with development. In the next section, we'll test it out in an iOS simulator.

## Running the app

Test the app by enabling notification and setting time 1 min in the future.

![](https://thepracticaldev.s3.amazonaws.com/i/4howshbmpeec1kjc9fax.gif)

> Note: Sometimes the notification may not show at the exact time. Please wait for a whole minute for notification to appear.

## Conclusion

We can now schedule daily local push notification in our React Native app for both iOS and Android.

Apart from firebase, there are other libraries you can use to implement local push notification like [react-native-push-notification](https://github.com/zo0r/react-native-push-notification).

Here is the Github repo [local-reminders](https://github.com/vikrantnegi/local-reminders).


> Originally published on [Medium](https://medium.com/better-programming/react-native-local-scheduled-push-notification-with-firebase-8c775b71c35c)


PS: Cover image by [Jamie Street](https://unsplash.com/@jamie452?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash