DEV Community

loading...

Creating a message component for displaying error in ReactJS

kitlung profile image Kit Lung Updated on ・2 min read

Hi,
Today I would like to share my way of displaying error or custom messages in React.
The idea is to use context and custom hook so we are able to access the component on all pages.

Custom Message Context Provider

Let's create a context provider first.

// CustomMessageProvider.tsx

import { createContext, useState } from 'react';

/*
* show : whether show or hide the message block
* type : what theme is the message block
* msg : message displaying on the message block
* 
* You can add more field if you want
*/
interface Msg {
  show: boolean;
  type: 'error' | 'info' | 'success' | 'warning';
  msg: string;
}

const defaultMsg = {
    show: false,
    type: 'success',
    msg: ''
} as Msg

export const CustomMessageContext = createContext({
    msg: defaultMsg as Msg,
    setMsg: (_: Msg) => {}
})

export const CustomMessageProvider = ({children}) => {
    const [msgState, setMsgState] = useState(defaultMsg)

// CustomMessageContext contains an object 
// and also a method for setState

    const contextValue = {
        msg: msgState,
        setMsg: (val: Msg) => setMsgState(val)
    }
    return (
        <CustomMessageContext.Provider value={contextValue}>
            {children}
        </CustomMessageContext.Provider>
    );
}
Enter fullscreen mode Exit fullscreen mode

Custom Snackbar

After that, create a custom snackbar using material-ui

// CustomSnackBar.tsx
const CustomSnackBar = () => {
    const { msg, setMsg } = useMsg();
    return (
        <Snackbar
          open={msg?.show}
          autoHideDuration={3000}
          onClose={() => {
              setMsg({ 
                  show: false,
                  type: msg.type, 
                  msg: '' 
              });
          }}>
          <Alert severity={msg.type}>{msg.msg}</Alert>
        </Snackbar>
    );
};

const Alert = (props) => {
    return (
        <MuiAlert 
            elevation={6} 
            variant="filled" 
            {...props} 
        />
    );
};

export default CustomSnackBar;
Enter fullscreen mode Exit fullscreen mode

Then we can add the provider to App.tsx so that we can access the context on all pages.

// App.tsx
const App = () => {
    <CustomMessageProvider>
        ...
        <CustomSnackBar />
    </CustomMessageProvider>
}
export default App
Enter fullscreen mode Exit fullscreen mode

Great!

Custom hook

What we are going to do now is to add a custom hook so we don't have to call useContext in all pages

// customMessageHook.tsx
const useMsg = () => {
    const { msg, setMsg } = useContext(CustomMessageContext);
    return { msg, setMsg };
}
export default useMsg;
Enter fullscreen mode Exit fullscreen mode

Integration

We can now call useMsg on all pages.
Let say you want to display an error if the fetch API failed on a page.

const { setMsg } = useMsg();

...

const fetchApi = async () => {
    try {
        ...
    } catch (err) {
        setMsg({
            show: true, 
            type: 'error',
            msg: 'Oops, error'
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

Alt Text

Ending

I know there are some more elegant ways to implement this, feel free to leave me a comment and share what you think.
Have a nice day.

Discussion (3)

pic
Editor guide
Collapse
ms_yogii profile image
Yogini Bende

This is a really nice pattern! Very useful one.

Collapse
t_pk_cd4c946778aa7e14a74e profile image
t pk

Nice one

Collapse
0xldev profile image
0xLDev

Very helpful