How chosey handles in-app announcements with React Native

In the chosey app, we have sometimes the need to send some information, warnings or guidance to the users in the app. One way we do this is sending in-app announcements to the users.

We use it for example to

  • Announce a downtime
  • Announce a new feature in the app
  • Celebrate or announce contests

In the following chapter I will show you how we handle these announcements in the react native frontend.

Give me some frontend code

The data structure of the announcements in chosey is as following:

export interface AnnouncementInterface {
    id: string;
  title: string;
  message: string;
  active?: true;
  image?: string;
  createdAt: string;
  endDate?: string;
}

The backend only returns the latest announcement that is still active and where the current date is before the endDate - so we don’t have to worry about that in frontend.

const startAnnouncementInterval = () => {
    getAnnouncement();
    const interval = setInterval(async () => {
      getAnnouncement();
    }, 60000);
    return () => {
      clearInterval(interval);
    };
  };

On page load we call the function startAnnouncementInterval() . This interval runs once if called and then every minute to check for new announcements.

const getAnnouncement = async () => {
    // API call to get lates announcement from server
  const announcement = await getLatestAnnouncement();   

    if (announcement?.id) {
            // the users id is part of the storage key in order to handle multiple accounts on one mobile phone
          const announcementStorageKey = 'announcement' + me?.id;

      // load the last saved announcement from local storage
      const lastSavedAnnouncement = await loadString(announcementStorageKey);
      if (announcement?.id) {
        // if this announcement is newer than the last saved one OR there is nothing in local storage -> show and update storage
        if (
          (lastSavedAnnouncement &&
            new Date(lastSavedAnnouncement) <
              new Date(announcement.createdAt)) ||
          !lastSavedAnnouncement
        ) {
          Alert.alert(announcement.title, announcement.message);
          await saveString(announcementStorageKey, announcement.createdAt);
        }
      }
    }
  };

The getAnnouncement() function gets the latest announcement from the backend and handles the logic if the announcement shall be shown or was already seen by the user.

I used a helper class in order to handle the local storage read and write operations - the used package is the @react-native-async-storage/async-storage

import AsyncStorage from '@react-native-async-storage/async-storage';
/**
 * Loads a string from storage.
 *
 * @param key The key to fetch.
 */
export async function loadString(key: string): Promise<string | null> {
  try {
    return await AsyncStorage.getItem(key);
  } catch {
    // not sure why this would fail... even reading the RN docs I'm unclear
    return null;
  }
}

/**
 * Saves a string to storage.
 *
 * @param key The key to fetch.
 * @param value The value to store.
 */
export async function saveString(key: string, value: string): Promise<boolean> {
  try {
    await AsyncStorage.setItem(key, value);
    return true;
  } catch {
    return false;
  }
}

I hope this post might help you within your projects!

Happy coding!