1

Before wrote this post, I saw this post, but i'm not able to link all of the code to mine.

This is my toggle component:

<ToggleContent
          toggle={show => (
            <div>
              <button type="button" onClick={show} className={styles.acronym}>
                {acronym}
              </button>
            </div>
          )
          }
          content={show => (
            <LogoutCard onClick={show} acronym={acronym} name={name} />
          )}
        />

and this is the inside of ToggleContent

function ToggleContent({ toggle, content }) {
  const [isShown, setIsShown] = useState(false);
  const hide = () => setIsShown(false);
  const show = () => setIsShown(!isShown);

  return (
    <Fragment>
      {toggle(show)}
      {isShown && content(hide)}
    </Fragment>
  );
}

and this is the wrapper of LogoutCard inside the props content

import React, { useRef, useEffect } from "react";

/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref) {
  /**
   * Alert if clicked on outside of element
   */
  function handleClickOutside(event) {
    if (ref.current && !ref.current.contains(event.target)) {
      alert("You clicked outside of me!");
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  });
}

/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);
  useOutsideAlerter(wrapperRef);

  return <div ref={wrapperRef}>{props.children}</div>;
}

Problem

The problem is that I'm able to print the alert, but i'm not able to close the popup because I'm not able to pass the show value, that's in the only allowed to close and open the little popup.

Question

How can I close the popup ?

Siri
  • 1,117
  • 6
  • 13
Legeo
  • 784
  • 4
  • 20
  • 44

1 Answers1

1

You need to pass a say a name, onClick function to handle the logic needed to execute to close the popup as needed. Also simplifying the logic to an toggle action that just negates the current state would be enough to manage the show / hide behaviour of the popup.

import React, { useRef, useEffect } from "react";

/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref, onClick) {
  /**
   * Alert if clicked on outside of element
   */
  function handleClickOutside(event) {
    if (ref.current && !ref.current.contains(event.target)) {
      alert("You clicked outside of me!");
      onClick();
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [handleClickOutside]);
}

/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);

  return <div ref={wrapperRef}>{props.children}</div>;
}

function ToggleContent({ toggle, content }) {
  const [isShown, setIsShown] = useState(false);

  const toggle = () => setIsShown(!isShown);

  const onClick = () => {
    toggle()
  }
  useOutsideAlerter(wrapperRef, onClick);

  return (
    <Fragment>
      {toggle(show)}
      {isShown && content()}
    </Fragment>
  );
}
Dez
  • 5,702
  • 8
  • 42
  • 51
  • just a question that can sound stupid, but consider it's my second month as web dev: i can reach the function ` useOutsideAlerter(wrapperRef, onClick); ` By import only the component OutsideAlerter ( the wrapper of logoutCard ) ? – Legeo Jun 28 '19 at 10:38
  • 1
    No. Also you should import it where it should be executed. And in your case, the place where it is appropriate is the `ToggleContent` component. `OutsideAlerter` is the function that you render inside `ToggleContent` through the prop `content`. – Dez Jun 28 '19 at 13:47