Developing a Powerful Alert System Using React Context API
To read more articles like this, visit my blog
React context API has supercharged our React applications. Now we can do stuff with pure React without any help from other libraries like Redux which was not possible before.
Today I will share how I used Context in a large-scale application.
We will build an alert system. Whenever any user clicks a button or user needs to see some information in a modal we will use Context to condense the logic inside one component.
Let’s begin…
Overview:
The main process will be something like this
We will create a context with a reducer.
We wrap the whole component with that context
Then from any component, we will trigger an action to update the value of the context
An alert component will consume the context, thus avoiding unnecessary re-render.
Whenever any update happens in the context, the Alert component will be triggered.
STEP 1: Lets Alert Types
Let’s first define what kind of alerts we will be dealing with here. Create a file named AlertTypes.ts . And put the following code there.
export enum AlertTypes {
SUCCESS= 'success',
ERROR = 'error',
WARNING = 'warning',
INFO = 'info',
NONE =' none'
}
Step 2: Alert Action
Now create an action file. We could create a single file with all the actions and reducers, but this is cleaner.
import { AlertTypes } from '../../types/AlertTypes'
export default class AlertAction {
static SHOW_ALERT = 'SHOW_ALERT'
static showSuccessAlert = (message) => {
return {
type: AlertAction.SHOW_ALERT,
payload: { message, type: AlertTypes.SUCCESS }
}
}
static showErrorAlert = (message) => {
return {
type: AlertAction.SHOW_ALERT,
payload: { message, type: AlertTypes.ERROR }
}
}
}
In this file, we have added 2 actions for now. Our showSuccessAlert()
function takes a single parameter as a message. This is the message that we will be showing to the users.
Step 3: Alert Reducer
Now we will create our reducer file. Our alert reducer is a simple function that checks the action type and sets the value of our state value.
import AlertAction from '../alert/AlertAction'
const AlertReducer = (state: any, action: any) => {
switch (action.type) {
case AlertAction.SHOW_ALERT:
return {
...state,
alertShower: action.payload
}
default:
return state
}
}
export default AlertReducer
Step 4: Alert Store
Now it’s time to create our store. We will be using the useReducer
hook of React. Our state has only 1 variable named alertShower
. This variable will hold the type
and message
of the alert.
import { createContext, useReducer } from 'react'
import { AlertTypes } from '../../types/AlertTypes'
import reducer from './GlobalReducer'
interface IAlertShower {
type: AlertTypes
message: string
}
interface IAlertState {
alertShower?: IAlertShower
}
const initialState: IAlertState = {
alertShower: {
type: AlertTypes.NONE,
message: ''
}
}
export const AlertContext = createContext<any>(initialState)
export const AlertProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState)
const value: any = [state, dispatch]
return <AlertContext.Provider value={value}>{children}</AlertContext.Provider>
}
Step 5: Wrap Component
Now we need to wrap our app with this context because alerts can be triggered from anywhere.
import React from 'react'
import { AlertProvider } from '../AlertProvider'
import AlertPopup from './general-components/AlertPopup'
function App() {
return (
<AlertProvider>
<div className='App'>
<AlertPopup />
<AnyComponent />
</div>
</AlertProvider>
)
}
export default App
Notice how we have included a special component named AlertPopup
. This will be our Alert component. We need this to be global as there will be only one alert component in the whole application.
Step 6: Alert Component
We are using Material-UI dialog for acting as our alert. You can use any design library or even use your own.
We don’t have to include this component over and over in all the places where we need to show the user some message.
import { Card, CardContent } from '@material-ui/core'
import Dialog from '@material-ui/core/Dialog'
import { Alert, AlertTitle } from '@material-ui/lab'
import React, { useContext, useEffect, useState } from 'react'
import { AlertContext } from './AlertContext'
import { AlertTypes } from '../types/AlertTypes'
export default function AlertPopup() {
const [state, dispatch] = useContext(AlertContext)
const [open, setOpen] = useState(false)
const [alertType, setAlertType] = useState<AlertTypes>(AlertTypes.NONE)
const [message, setMessage] = useState<string>('Some Message')
useEffect(() => {
const { message, type } = state.alertShower
setAlertType(type)
setMessage(message)
if (type !== AlertTypes.NONE) setOpen(true)
}, [state.alertShower])
const handleClose = () => setOpen(false)
return (
<Dialog open={open} onClose={handleClose} aria-labelledby='max-width-dialog-title'>
<Card variant='outlined'>
<CardContent>
<Alert severity={alertType}>
<AlertTitle>{message}</AlertTitle>
</Alert>
</CardContent>
</Card>
</Dialog>
)
}
Step 7: Use the Alert
Now we need to test what we have created for ourselves. Create a button named AlertButton.tsx
. Place this component anywhere you want.
This button will dispatch an action that will update the value of the alert context, which in turn triggers our alert component.
import React, { useContext } from 'react'
import AlertAction from '../../data/alert/AlertAction'
import { AlertContext } from './AlertStore'
export default function AlertButton() {
const [state, dispatch] = useContext(AlertContext)
const showAlert = () => dispatch(AlertAction.showErrorAlert('An Error Occurred'))
return <button onClick={showAlert}> Show Alert </button>
}
How awesome is that?
Food for thought
So, what will you do if you need to add some action to this alert modal? Can you do that?
Conclusion
This article is a practical guide on using React’s Context API to build real-life applications.
Almost all applications will need some feedback mechanism. I hope this can help. Let me know if you didn’t understand anything.
Have something to say? Get in touch with me via LinkedIn or Personal Website