Creating a Simple Toast Component in React with Custom Hooks

Creating a Simple Toast Component in React with Custom Hooks

But first, what are Custom Hooks?

A Custom Hook is a technique that allows you to encapsulate a component's logic into a reusable function. Custom Hooks are functions in JavaScript that utilize the Hooks provided by React, such as useState, useEffect, useCallback, etc. For a function to be considered a Custom Hook, it must start with the prefix "use" and use at least one React Hook.

Now that we understand what a Custom Hook is, let's apply it to our component. A Toast is a simple component often used to display information to the user after an action. Our goal is to create a Toast that can be reused in any context within the application, providing an efficient and consistent way to show feedback messages to the user.


First Step

First, we'll add a <div> to our root component to serve as the wrapper for our Toast.

function App() {
   return (
    <>
      <div className="App"></div>
      <div id="container-toast"></div>
     </>
   );
}        

Custom Hook - useTimeout

Next, we'll create our first Custom Hook, useTimeout. This Custom Hook will be responsible for executing a function provided as a parameter after a specified time interval, also provided as a parameter. We will use the useEffect hook and the setTimeout function from the Web API.

const useTimeout = (callback, delay = 3000, dependencies = []) => {
     useEffect(() => {
       const timeoutId = setTimeout(() => {
          callback()
      }, delay)

      return () => {
         clearTimeout(timeoutId)
      }
 }, [delay, ...dependencies])
}        

Make a Toast Component

Now we need our Toast component.

const ToastComponent = ({ acceptHtml, message, delay, onClose }) => {
 useTimeout(
   () => {
     onClose();
   },
   delay,
   [onClose]
 );

 if (acceptHtml) {
   return <div className={styles.toast} dangerouslySetInnerHTML={{ __html: message }} />;
 }

 return (
   <div className={styles.toast}>
     <span>{message}</span>
   </div>
 );
};        

Our component receives 4 props:

  • onClose: A function that will be executed by the Custom Hook when the component is closed. As the name suggests, this function handles the component's closing action.
  • delay: The wait time before executing the function, in milliseconds.
  • message: The message to be displayed in the toast.
  • acceptHtml: If the message contains HTML tags and you want them to be rendered correctly, set this prop to true.

We need to add styles to the component. The basic required style is absolute positioning and the placement where you want the toast to appear. Don’t be like me; get creative to enhance the appearance of your component. ??

.toast {
   position: absolute;
   right: 34px;
   width: 200px;
   height: 100px;
   border: 1px solid red;
}        

The function that shows the toast

With the component ready, let's create the function responsible for displaying the toast on the screen.

const showToast = ({ delay = 3000, acceptHtml = false, message }) => {
 const container = document.getElementById("container-toast");
 const root = createRoot(container);

 const handleClose = () => {
   const toastElement = document.getElementById("container-toast");
   root.unmount(toastElement);
 };
 const toast = (
   <ToastComponent
     delay={delay}
     onClose={handleClose}
     acceptHtml={acceptHtml}
     message={message}
   />
 );
 root.render(toast, container);
};        

Our function locates the project's root container, "container-toast," and renders the ToastComponent within it. The handleClose function performs the opposite operation by locating the element in the DOM and removing it. Remember that the onClose prop is executed within our useTimeout. Therefore, when the delay time expires, the component will be removed from the screen. Simple, right?


Usage

And how to use it? You can simply call the showToast function in response to a button click.

unction App() {
 return (
   <div className="App">
     <button onClick={() => { showToast({
       message: "Hello! I'm a Toast! "
     }) }}>Click me!</button>
     <div id="container-toast"></div>
   </div>
 );
}        

We can also create another Custom Hook that will only be executed when a specific condition is true.

const useToast = (conditionShowToast, message, delay, acceptHtml) => {
 useEffect(() => {
   if(conditionShowToast) {
     showToast({
       message,
       delay,
       acceptHtml
     })
   }
 }, [conditionShowToast])
}        

Conclusion

Finally, you have a simple Toast ready to be used throughout your application, implemented using the Custom Hook pattern! I’m available for any tips, suggestions for improvements, or comments.

Danilo Pereira

Mobile Engineer | React Native Developer | React | TypeScript | JavaScript | Mobile Developer | Node

7 个月

Very informative Otávio Soares!

要查看或添加评论,请登录

Otavio Soares的更多文章

  • BEM Methodology: Simplifying CSS

    BEM Methodology: Simplifying CSS

    Have you ever experienced the chaos of a project where modifying the CSS felt like navigating a maze? You try to tweak…

    3 条评论
  • Using Open/Closed Concept in hooks

    Using Open/Closed Concept in hooks

    SOLID is a design pattern commonly used in various programs. Some developers think that the concepts from SOLID can…

    2 条评论
  • The Prop Drilling Problem

    The Prop Drilling Problem

    React is a great framework for building larger applications using scalable, reusable, and maintainable components…

  • 4 simple ways to start achieving DRY in React

    4 simple ways to start achieving DRY in React

    The DRY definition The DRY principle is a simple concept, stands for "DON'T REPEAT YOURSELF". This concept has aims…

    6 条评论
  • Context Module Pattern

    Context Module Pattern

    Particulamente, gosto de aprender alguns padr?es de desenvolvimento pois na maioria das vezes sempre s?o solu??es que…

  • Porque evitar utilizar muitos re-exporting ?

    Porque evitar utilizar muitos re-exporting ?

    Publica??o incentivada pela eNe Soluc?es no nosso pilar Never Stop Learning. Você já deve ter visto algum arquivo que a…

社区洞察

其他会员也浏览了