React useContext hook to make an alert / notification system for your entire application

Jumanah Al Asadi
4 min readOct 14, 2021

Need a way to trigger alerts from anywhere in your React or Nextjs app? A great way to utilize, useContext. 🆒

We will use React context to store a global state for an app wide notification / alert, which can be updated at anytime, from any component.

Let’s start off by creating a new context using React, in the context folder (create one if you don’t have it already), we can call it notificationContext.js

context /notificationContext.js

  • Import React
  • Create a context using React.createContext({}) pass it empty values or the shape for what your global state should look like, as well as your own methods to update it. Here we include the global state variables and the methods to update the global state.
import React, { useState } from 'react';const NotificationContext = React.createContext({
notification: null,
notificationText: null,
success: () => {},
error: () => {},
});

We can also define our alert states, as constants, in this file. This is optional, but good to do. (optional) 🚦

const STATES = {
SUCCESS: 'success',
ERROR: 'error',
};

Then we create a NotificationProvider component from the React context we created earlier. This Context provider component is used as a wrapper, to wrap around our entire application, so that the app is nested inside it. It will give all our application access to set the notification state and to clear it with the functions we defined up above.

This component will have the actual implementation of the state and the methods to update it.

The state variables will be:

  • notification: which stores the type (“success”, “error”)
  • notificationText: which stores the custom message to display

The function to update the state will be:

  • success (text): called with a text to display a green success message âś…
  • error (text): called with a text to display a red error message đź”´
  • clear: called to clear the alert / notification
const NotificationProvider = (props) => {
const [notification, setNotification] = useState(null);
const [notificationText, setNotificationText] = useState(null);
const success = (text) => {
window.scroll(0, 0);
setNotificationText(text);
setNotification(STATES.SUCCESS);
};
const error = (text) => {
window.scroll(0, 0);
setNotificationText(text);
setNotification(STATES.ERROR);
};
const clear = () => {
setNotificationText(null);
setNotification(null);
};
return (
<NotificationContext.Provider
value={{
success, error, clear, notification, notificationText,
}}
>
{props.children}
</NotificationContext.Provider>
);
};

Then we export both the context and the provider at the end of the file. We need to import them later to actually use them.

export { NotificationProvider };
export default NotificationContext;

We need to allow our components to have access to this globalstate and these functions to update it. To do this, let’s wrap the Notification provider component around our entire application, we can do this wherever our main app lives. This can be app.js or index.js. We used props.children so anything nested inside this wrapper component will be displayed as before.

app.js

import { NotificationProvider } from 'context/notificationContext';function App() {

...
return (
<NotificationProvider>
<Router>
...
</Router>
</NotificationProvider>
);
}

After we wrap the provider around our app, it is now available for use, with the useContext hook!

Something else we still need to also create an Alert or Notification component to display this notification which exists inside context.

Inside components, create a component called Notification.

This component will always be displayed at the top of your application. It might not always render, if the notification is set to null. It will only display if a notification is present in the global state or context.

It will take from the context the notification state to style the component accordingly (please add your styles), and the notificationText state to display the correct message. This is a simplified version of the notification alert component.

  • Import useContext hook from React
  • Pass it your context
  • Now you can reference your context.

components/Notification/index.js

import React from 'react';
import { useContext } from 'react';
import NotificationContext from 'context/notificationContext';const NotificationBar = () => {
const notificationCtx = useContext(NotificationContext);
return (
notificationCtx.notification !== null && (
<div className={notificationCtx.notification}>
<p> notificationCtx.notificationText </p> </div>
)
);
};
export default NotificationBar;

Then we will need to display this component, somewhere. Preferably, in app.js, because it should be rendered / overlaying, for the entire app. Note: Make sure to put it within the notification provider wrapper component, because it also needs access to the context as well!

app.js

import { NotificationProvider } from 'context/notificationContext';
import NotificationBar from 'components/Notification';
function App() {

...
return (
<NotificationProvider>
<NotificationBar />
<Router>
...
</Router>
</NotificationProvider>
);
}

Ok great — but now we have no alert or notification because we still haven’t called a success or error alert yet to set the notification state.

So anywhere we want to trigger an alert or notification we need to call the context functions.

  • We import the context we created and useContext hook from React
  • We call the methods, success or error with the text we want to display.

So in any random component or page in your application. Do the same..

components/Project/index.js

Note: In the below example, we are fetching a project from an API, and when it fails we display an error notification.

import { useState, useEffect, useContext } from 'react';
import NotificationContext from 'context/notificationContext';
const axios = require('axios');
const Project = () => { const notificationCtx = useContext(NotificationContext); useEffect(() => {
fetchProject();
}, []);
const fetchProject = async () => {try {
const response = await axios.get(`${process.env.apiServer}/${projectId}`);
notificationCtx.success('Success: Project was fetched!');
} catch (err) {
console.log(err);
notificationCtx.error('Technical Error: Error fetching data');
}
}
return ( .. )
};
export default Project

That’s all you need! 🆒 🆒 🆒

--

--

Jumanah Al Asadi

I am just a web developer who loves writing, teaching and music :) My teaching style is playful and fun. At least I hope, lol :p