@linio/react-notifications

A notification system for React built with the Context API

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
@linio/react-notifications
0.2.16 years ago6 years agoMinified + gzip package size for @linio/react-notifications in KB

Readme




yarn add @linio/react-notifications

Features

  • Load and store notifications to external services (defaults to localStorage)
  • Read/unread status
  • Toast notifications
  • Push (web) notifications

User Guide

Table of Contents

- NotificationProvider - NotificationConsumer - context.create - .persist() - .toast() - .push() - context.notifications - context.markAsRead - storageProvider.load - storageProvider.store

Getting Started

@linio/react-notifications is built on top of React's Context API, therefore exposing a Provider and Consumer pair:
import { NotificationProvider, NotificationConsumer } from '@linio/react-notifications';
NotificationProvider
The NotificationProvider "provides" the context of your notification system to your app. It should be added to the top of your component tree. If you are using other Provider components from libraries such as redux or styled-components then this concept should be familiar to you.
// App.js

import { NotificationProvider } from '@linio/react-notifications';

class App extends Component {
  // ...

  render() {
    return (
      <NotificationProvider>
        {/* App code */}
      </NotificationProvider>
    );
  }
}
NotificationConsumer
The NotificationConsumer allows you to "consume" the context of your notification system. It must render at any level beneath NotificationProvider in the application tree.
// MyComponent.js

import { NotificationConsumer } from '@linio/react-notifications';

const MyComponent = () => (
  <NotificationConsumer>
    {context => {
      /* where the magic happens! */
    }}
  </NotificationConsumer>
);

// App.js

import { NotificationProvider } from '@linio/react-notifications'
import MyComponent from './MyComponent'

class App extends Component {
  // ...

  render() {
    return (
      <NotificationProvider>
        <MyComponent />
      </NotificationProvider>
    }
  }
}

MyComponent now has access to your notification system's context! 💥

Creating a notification

A notification can be created using the context.create method.
context.create
<NotificationConsumer>
  {({ create }) => {
    const notification = create(options);
  }}
</NotificationConsumer>

options
title
type: string
required: true
The title that will appear on the notification if rendered.
level
type: 'SUCCESS', 'WARNING' or 'ERROR'
required: true
Assigns a priority level to the notification. Also used internally for styling toast notifications.
body
type: string or Function
required: false
// text body

const notification = create({
  title: 'Rich notification',
  level: 'SUCCESS',
  body: 'Im boring!'
});

// rich notification body

const notification = create({
  title: 'Rich notification',
  level: 'SUCCESS',
  body: () => <p>Im rich!</p>
});

The body property is used by both toast and push notifications, however, push notification can only receive a body with the type string. Toast notifications, on the other hand, can have a body with the type string or Function, where the Function should resemble a stateless functional component and returns some html.
If a Function is passed, @linio/react-notifications will call that function and store the resulting html for later use. This allows you to add more than just text. A link perhaps? 😏
requireInteraction
type: boolean
required: false
If set to true, the notification will appear static on the screen (either as a toast or push notification) without dismissing itself after a set period of time (~5s).

The notification object

When you call the create method, a notification object is returned, allowing you to take action in any way you see fit:
const notification = create(options);

notification.persist();
notification.toast();
notification.push();
.persist()
Stores the notification in context.notifications.
.toast()
Renders a toast notification.
.push()
Creates a web notification by first checking the user's browser permissions. If denied, it will create a toast notification.


By default, the toast and push methods do not "persist" notifications. They will simply render them to the screen and then disappear quietly into the ether. However, you can chain the persist method to opt-in to such functionality:
// render a toast notification and persist it for later access

notification
  .toast()
  .persist();

// render a push notification and persist it for later access

notification
  .push()
  .persist();

Accessing persisted notifications

Notifications that have been persisted with .persist or that have been loaded from a storageProvider are accessible via the context.notifications array.
context.notifications
<NotificationConsumer>
  {({ notifications }) => notifications.map(notification => { /* do stuff */})}
</NotificationConsumer>

// structure of a notification

{
  id: string,
  title: string,
  level: 'SUCCESS' | 'WARNING' | 'ERROR',
  timestamp: Date,
  read: boolean,
  options: {
    body?: string | Function,
    requireInteraction?: boolean
  }
}

Marking a notification as read

When a notification is created, it will contain a read property that defaults to false. If you are persisting notifications and rendering them somewhere in your application, it is possible to expose read/unread functionality to your users through the context.markAsRead method:
context.markAsRead
<NotificationConsumer>
  {({ markAsRead }) => {
    // ...
    markAsRead(notification.id)
  }}
</NotificationConsumer>

options
id
type: string
required: true
The id of the notification you wish to mark as read.

Writing your own storageProvider

By default, @linio/react-notifications will load and store persisted notifications from localStorage. This behavior requires no configuration on your part. You can, however, override this behavior to load and store persisted notifications from an external service of your own using a storageProvider.
A storageProvider is an object containing two methods, load and store. Each method is called at certain points of your application's lifecycle.
// storageProvider.js

export const load = () => notifications
export const store = data => {} 

To link the storageProvider to your notification system, pass the functions as load and store props to NotificationProvider.
// App.js

import { NotificationProvider } from '@linio/react-notifications';
import { load, store } from './storageProvider';

class App extends Component {
  // ...

  render() {
    return (
      <NotificationProvider load={load} store={store}>
        {/* App code */}
      </NotificationProvider>
    );
  }
}

Alternatively, if your app supports object rest/spread, you can use this nifty syntactic sugar:
// App.js
import { NotificationProvider } from '@linio/react-notifications';
import * as storageProvider from './storageProvider';

class App extends Component {
  // ...

  render() {
    return (
      <NotificationProvider {...storageProvider}>
        {/* App code */}
      </NotificationProvider>
    );
  }
}
storageProvider.load
Should return an array of persisted notifications.
// storageProvider.js

const load = () => { /* returns an array of notifications */ }

When is storageProvider.load called?
The storageProvider.load method is called when NotificationProvider mounts, and it will initialize your notification system's context with the returned array.
storageProvider.store
Accepts a single notification or an array of notifications.
// storageProvider.js

const store = data => { /* data === notification || Array<notification>*/}

When is storageProvider.store called?
Each time a notification is persisted using the .persist() method, @linio/react-notifications will check to see if you have provided a custom storageProvider with a store method on it. If you have, this method will receive the newly persisted notification.

Contributing

git clone git@github.com:LinioIT/react-notifications.git

yarn test

Tooling

@linio/react-notifications uses the following tools internally:
  • babel 🐠 for transpiling JavaScript for the browser
  • rollup to bundle for production
  • prettier for code formatting
  • jest 🃏 test runner