Search code examples
reactjsreact-bootstraptoast

Hide react bootstrap toast when user clicks outside


I have a toast notification created using react-bootstrap. I need to dismiss it if the user clicks anywhere outside the toast. Someone knows how can I do that?

This is the toast I'm using:

//what am I importing
import { Toast } from 'react-bootstrap';

//how am I using it
<Toast
    onClose={() => props.OnClose(false)}
    data-testid="toast"
    show={props.Show}
    delay={10000}
    autohide
>
    <Toast.Header closeButton={false}>
        <div>
            {props.Icon}
        </div>
        <div>
            Title
        </div>
        <div
            onClick={() => props.OnClose(false)}
        >
            <ToastClose />
        </div>
    </Toast.Header>
    <Toast.Body>
        Body text
    </Toast.Body>
</Toast>

Solution

  • What you can use is React hook useRef. Using useRef hook we can access the DOM elements easily and in this case we are accessing the Toast component and tracking clicks that happen outside of the component and firing the setShow(false) to update the state and dismiss the Toast component. This code will dismiss the Toast if the user clicks anywhere outside of it:

    import { Toast } from "react-bootstrap";
    import { useState, useRef, useEffect } from "react";
    
    export default function App() {
      const [show, setShow] = useState(true);
    
      function useOutsideAlerter(ref) {
        useEffect(() => {
          /**
           * Close toast if clicked on outside of element
           */
          function handleClickOutside(event) {
            if (ref.current && !ref.current.contains(event.target)) {
              setShow(false);
            }
          }
          // Bind the event listener
          document.addEventListener("mousedown", handleClickOutside);
          return () => {
            // Unbind the event listener on clean up
            document.removeEventListener("mousedown", handleClickOutside);
          };
        }, [ref]);
      }
    
      const wrapperRef = useRef(null);
      useOutsideAlerter(wrapperRef);
    
      return (
        <div className="App">
          <Toast
            onClose={() => setShow(false)}
            data-testid="toast"
            show={show}
            delay={10000}
            autohide
            ref={wrapperRef}
          >
            <Toast.Header closeButton={false}>
              <div>Toast title</div>
              <div onClick={() => setShow(false)}>Close button</div>
            </Toast.Header>
            <Toast.Body>Body text</Toast.Body>
          </Toast>
        </div>
      );
    }
    

    Original post with more info: link