首页 > 解决方案 > 如何使用组件更改 dom 元素

问题描述

import {
  NotificationIcon,
  SummaryIcon,
  PublishIcon,
  EngageIcon,
  ListenIcon,
  ReportIcon,
  PlusIcon,
  MinusIcon,
} from "../../icons/Icons";
import "./Sidebar.scss";
import ReactDOM from "react-dom";



const Sidebar = () => {
  

  // handle accordion menu's open effect
  const handleClassName = (arg) => {
    const element = document.getElementById(arg);
    element.classList.toggle("show");
    element.firstElementChild.lastElementChild.remove()

  };

  const handleBrandsIcon = (arg) => {
    const allBrands = document.querySelectorAll(".sidebar__brand");
    for (let i = 0; i < allBrands.length; i++) {
      allBrands[i].classList.remove("active");
      document.getElementById(arg).classList.add("active");
    }
  };



  const contentBox = [
    {
      id: 0,
      icon: <SummaryIcon className="sidebar__icon" />,
      label: "SUMMARY",
      iconType: "summary",
    },
    {
      id: 1,
      icon: <PublishIcon className="sidebar__icon" />,
      label: "PUBLISH",
      iconType: "publish",
    },
    {
      id: 2,
      icon: <EngageIcon className="sidebar__icon" />,
      label: "ENGAGE",
      iconType: "engage",
    },
    {
      id: 3,
      icon: <ListenIcon className="sidebar__icon" />,
      label: "LISTEN",
      iconType: "listen",
    },
    {
      id: 4,
      icon: <ReportIcon className="sidebar__icon" />,
      label: "REPORT",
      iconType: "report",
    },
  ];

  const brands = [
    {
      img: "./gucci.gif",
      id: 10,
    },
    {
      img: "./coca-cola.gif",
      id: 11,
    },
    {
      img: "./pepsi.gif",
      id: 12,
    },
    {
      img: "./samsung.png",
      id: 13,
    },
    {
      img: "./tesla.gif",
      id: 14,
    },
    {
      img: "./twitter.png",
      id: 15,
    },
  ];

  return (
    <div className="sidebar">
      <h2 className="sidebar__header">
        sociality<label>.io</label>
      </h2>
      <div className="sidebar__wrapper">
        <div className="sidebar__brands">
          {brands.map((brand) => {
            return (
              <div
                id={brand.id}
                className="sidebar__brand"
                onClick={() => handleBrandsIcon(brand.id)}
              >
                <img src={brand.img} className="sidebar__img" alt="/" />
              </div>
            );
          })}
        </div>
        <div className="sidebar__accordion">
          <div className="sidebar__content-box">
            <div className="sidebar__row">
              <NotificationIcon />
              <label className="sidebar__label">NOTIFICATIONS</label>
              <label className="sidebar__label sidebar__label--rounded">
                28
              </label>
            </div>
            <ul className="sidebar__list">
              <li className="sidebar__item">Compase</li>
              <li className="sidebar__item">Feed</li>
            </ul>
          </div>

          {contentBox.map((content) => {
            return (
              <div
                id={content.id}
                className="sidebar__content-box"
                onClick={() => handleClassName(content.id)}
              >
                <div className="sidebar__row">
                  {content.icon}
                  <label className="sidebar__label">{content.label}</label>
                  <PlusIcon className="sidebar__plus" />
                </div>
                <ul className="sidebar__list">
                  <li className="sidebar__item">Compase</li>
                  <li className="sidebar__item">Feed</li>
                </ul>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
};

export default Sidebar;

嗨,伙计们有美好的一天。当我单击具有.sidebar__row类名的 div 元素时,我想更改<PlusIcon/><MinusIcon/>。我将其推进到删除<PlusIcon/>组件的阶段,但我无法以任何方式添加<MinusIcon/>组件而不是<PlusIcon/>。此外,我尝试添加ReactDOM.render(<MinusIcon className="sidebar__plus" /> , element.firstChild)结束handleClassName函数,我可以添加而不是但是这次所有子元素<div className="sidebar__row">都被删除了。最后,如果你在我的代码中看到任何荒谬的东西,你可以给我建议,让我编写更干净的代码。

标签: javascriptreactjsdom

解决方案


添加状态以保存当前选定的品牌 ID,"active"如果当前映射的品牌 ID 与状态匹配,则有条件地添加类。

添加状态以保存切换的内容 id 的映射,并有条件地在当前内容的 id 匹配上呈现无序列表和加号/减号图标。

contentBox和数组是静态的brands,因此它们可以从组件中拉出,在组件之外定义。

const contentBox = [.....];

const brands = [.....];

const Sidebar = () => {
  const [showBrandId, setShowBrandId] = React.useState(null);
  const [showContentIds, setShowContentIds] = React.useState({});

  // handle accordion menu's open effect
  const handleClassName = (contentId) => {
    setShowContentIds(ids => ({
      ...ids,
      [contentId]: !ids[contentId], // toggles boolean
    }));
  };

  const handleBrandsIcon = (brandId) => {
    setShowBrandId(brandId); // replaces current active brand
  };

  return (
    <div className="sidebar">
      <h2 className="sidebar__header">
        sociality<label>.io</label>
      </h2>
      <div className="sidebar__wrapper">
        <div className="sidebar__brands">
          {brands.map((brand) => {
            return (
              <div
                id={brand.id}
                className={"sidebar__brand " + brand.id === showBrandId ? "active" : ""}
                onClick={() => handleBrandsIcon(brand.id)}
              >
                <img src={brand.img} className="sidebar__img" alt="/" />
              </div>
            );
          })}
        </div>
        <div className="sidebar__accordion">
          <div className="sidebar__content-box">
            <div className="sidebar__row">
              <NotificationIcon />
              <label className="sidebar__label">NOTIFICATIONS</label>
              <label className="sidebar__label sidebar__label--rounded">
                28
              </label>
            </div>
            <ul className="sidebar__list">
              <li className="sidebar__item">Compase</li>
              <li className="sidebar__item">Feed</li>
            </ul>
          </div>

          {contentBox.map((content) => {
            const showContent = showContentIds[content.id];
            return (
              <div
                id={content.id}
                className={"sidebar__content-box" + showContent ? "show" : ""}
                onClick={() => handleClassName(content.id)}
              >
                <div className="sidebar__row">
                  {content.icon}
                  <label className="sidebar__label">{content.label}</label>
                  {showContent ? (
                    <MinusIcon className="sidebar__minus" />
                  ) : (
                    <PlusIcon className="sidebar__plus" />
                  )}
                </div>
                {showContent && (
                  <ul className="sidebar__list">
                    <li className="sidebar__item">Compase</li>
                    <li className="sidebar__item">Feed</li>
                  </ul>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
};

推荐阅读