DEV Community

Kit Lung
Kit Lung

Posted on • Edited on

12 1

Creating a message component for displaying error in ReactJS

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.

Top comments (3)

Collapse
 
hey_yogini 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

This post blew up on DEV in 2020:

js visualized

🚀⚙️ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! 🥳

Happy coding!

AWS Industries LIVE!

AWS Industries LIVE! features AWS Partners discussing various topics related to their industry, their solutions, and how they can help customers.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️