React - 通过单击显示元素,并通过单击元素外部和元素隐藏元素

问题描述 投票:0回答:1

我必须建立带有通知徽章的通知铃(用于通知数量)。 当我单击响铃时,通知徽章消失,并显示带有通知的下拉列表。 这部分已经完成了。

接下来,当我单击该下拉通知列表或其中(页面上的任何位置)列表时,列表将关闭。 那也可以。

但是当下拉列表打开并且我单击通知铃(或其包装器)时,列表应该关闭(再次隐藏)。但这是行不通的。另外,也许通知徽章消失会很好,因为列表已打开,但通过单击铃进行切换是我在这里的主要问题。

欢迎任何帮助! 这是我的代码:

import { useState, useEffect, useRef } from 'react';
import { Effect } from 'react-notification-badge';
import NotificationBadge from 'react-notification-badge/lib/components/NotificationBadge';
import logoIcon from '../images/logo.svg';
import notificationIcon from '../images/notification.svg';

const TopBar = () => {
  const [notifBadgeIsShown, setNotifBadgeShown] = useState(false);

  useEffect(() => {
    document.addEventListener('click', handleClick, true);
  });

  const refOne = useRef(null);

  const handleClick = (e) => {
    if (!refOne.current.contains(e.target)) {
      setNotifBadgeShown(false);
    }
    if (refOne.current.contains(e.target)) {
      setNotifBadgeShown(false);
    }
  };

  const notifications = ['Notification 1', 'Notification 2'];

  let listItems = notifications.map((number) => (
    <li key={number.toString()}>{number}</li>
  ));

  return (
    <div className="top-bar">
      <img className="logo-icon" src={logoIcon} alt="Logo icon" />
      <div
        className="notification-wrapper"
        onClick={() =>
          notifBadgeIsShown === false
            ? setNotifBadgeShown(true)
            : setNotifBadgeShown(false)
        }
      >
        {!notifBadgeIsShown ? (
          <NotificationBadge
            className="notif-badge"
            count={notifications.length}
            effect={Effect.SCALE}
          />
        ) : null}
        {notifBadgeIsShown ? <div className="dropdown">{listItems}</div> : null}

        <img
          className="notification-icon"
          src={notificationIcon}
          alt="Notification icon"
          ref={refOne}
        />
      </div>
    </div>

  );
};

export default TopBar;

我尝试用 useRef 来做到这一点,但仍然没有预期的结果......

reactjs toggle hide show use-ref
1个回答
0
投票
  import { useState, useEffect, useRef } from 'react';
import { Effect } from 'react-notification-badge';
import NotificationBadge from 'react-notification-badge/lib/components/NotificationBadge';
import logoIcon from '../images/logo.svg';
import notificationIcon from '../images/notification.svg';

const TopBar = () => {
  const [isNotifBadgeShown, setNotifBadgeShown] = useState(false);
  const refOne = useRef(null);

  useEffect(() => {
    const handleClick = (e) => {
      if (!refOne.current.contains(e.target)) {
        setNotifBadgeShown(false);
      }
    };

    document.addEventListener('click', handleClick);
    return () => {
      document.removeEventListener('click', handleClick);
    };
  }, []);

  const toggleNotification = () => {
    setNotifBadgeShown((prev) => !prev);
  };

  const notifications = ['Notification 1', 'Notification 2'];
  const notificationCount = notifications.length;

  return (
    <div className="top-bar">
      <img className="logo-icon" src={logoIcon} alt="Logo icon" />
      <div className="notification-wrapper" onClick={toggleNotification}>
        {!isNotifBadgeShown && (
          <NotificationBadge
            className="notif-badge"
            count={notificationCount}
            effect={Effect.SCALE}
          />
        )}
        {isNotifBadgeShown && (
          <div className="dropdown">
            <ul>
              {notifications.map((notification, index) => (
                <li key={index}>{notification}</li>
              ))}
            </ul>
          </div>
        )}
        <img
          className="notification-icon"
          src={notificationIcon}
          alt="Notification icon"
          ref={refOne}
        />
      </div>
    </div>
  );
};

export default TopBar;
© www.soinside.com 2019 - 2024. All rights reserved.