Jordan Ferr
Jordan Ferr

Reputation: 319

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>

Upvotes: 1

Views: 2516

Answers (1)

Stefan
Stefan

Reputation: 260

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

Upvotes: 2

Related Questions