首页 > 解决方案 > 关于如何在 React 中对这个导航栏进行 DRY 编码的任何想法?

问题描述

我正在使用 React 创建一个 SPA,并注意到在创建我的导航栏时会有很多重复。我想要的是这样的六个组件:

function Navbar() {
   return (
     <nav className="navbar">
       <div className="navbar-items">
         <Logo />
         <NavbarItem1 />
         <NavbarItem2 />
         <NavbarItem3 />
         <NavbarItem4 />
         <NavbarItem5 />
       </div>
     </nav>
   )
}

现在对于重复部分,每个组件基本上都是这样的:

function NavbarItem1() {
   return (
     <div className="navbar-item">
       <button className="navbar-button">
         <svg class="navbar-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 80" x="0px" y="0px">
          <g>
            <path
              d="M52,7a5.006,5.006,0,0,0-5-5H7A5.006,5.006,0,0,0,2,7V56H4V7A3,3,0,1,1,8,9.816V7H6V62H48V11.9A5.009,5.009,0,0,0,52,7ZM8,60V12H46V60ZM47,10H10.974a4.9,4.9,0,0,0,0-6H47a3,3,0,0,1,0,6Z" />
            <path
              d="M57,8a5.006,5.006,0,0,0-5,5V52.236l5,10,5-10V13A5.006,5.006,0,0,0,57,8ZM56,48.586,54.845,47.43,54,48.7V22h2Zm-1.846,3.486,1-1.5L57,52.414l1.845-1.844,1,1.5L57,57.764ZM60,48.7l-.845-1.267L58,48.586V22h2ZM60,20H54V18h6Zm-6-4V13a3,3,0,0,1,6,0v3Z" />
            <rect x="12" y="20" width="30" height="2" />
            <rect x="12" y="28" width="30" height="2" />
            <rect x="12" y="35" width="30" height="2" />
            <rect x="12" y="43" width="30" height="2" />
            <rect x="12" y="50" width="18" height="2" />
            <rect x="36" y="50" width="2" height="2" />
            <rect x="32" y="50" width="2" height="2" />
            <rect x="40" y="50" width="2" height="2" />
          </g>
        </svg>
        <span class="navbar-text">Item 1</span>
       </button>
     </div>
   )
}

因此,与其创建六个基本相同的组件,是否有一种重复性较低的方式来执行此操作,或者这是人们使用 React 创建导航栏的正常方式?提前感谢您的回答。

标签: htmlreactjsjsxdry

解决方案


假设每个导航栏项之间不同的部分是图标及其文本内容,您可以将图标提取到自己的组件中,然后只需通过 props 传递图标组件和文本:

// Pass className via props so the NavbarItem can set it
function NoteIcon({ className }) {
  return (
    <svg
      className={className}
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 64 80"
      x="0px"
      y="0px"
    >
      <g>
        <path d="M52,7a5.006,5.006,0,0,0-5-5H7A5.006,5.006,0,0,0,2,7V56H4V7A3,3,0,1,1,8,9.816V7H6V62H48V11.9A5.009,5.009,0,0,0,52,7ZM8,60V12H46V60ZM47,10H10.974a4.9,4.9,0,0,0,0-6H47a3,3,0,0,1,0,6Z" />
        <path d="M57,8a5.006,5.006,0,0,0-5,5V52.236l5,10,5-10V13A5.006,5.006,0,0,0,57,8ZM56,48.586,54.845,47.43,54,48.7V22h2Zm-1.846,3.486,1-1.5L57,52.414l1.845-1.844,1,1.5L57,57.764ZM60,48.7l-.845-1.267L58,48.586V22h2ZM60,20H54V18h6Zm-6-4V13a3,3,0,0,1,6,0v3Z" />
        <rect x="12" y="20" width="30" height="2" />
        <rect x="12" y="28" width="30" height="2" />
        <rect x="12" y="35" width="30" height="2" />
        <rect x="12" y="43" width="30" height="2" />
        <rect x="12" y="50" width="18" height="2" />
        <rect x="36" y="50" width="2" height="2" />
        <rect x="32" y="50" width="2" height="2" />
        <rect x="40" y="50" width="2" height="2" />
      </g>
    </svg>
  );
}

function NavbarItem({ icon: Icon, children }) {
  return (
    <div className="navbar-item">
      <button className="navbar-button">
        <Icon className="navbar-icon" />
        <span className="navbar-text">{children}</span>
      </button>
    </div>
  );
}

function Navbar() {
  return (
    <nav className="navbar">
      <div className="navbar-items">
        <Logo />
        {/* Pass the correct icon component, and the text via children */}
        <NavbarItem icon={NoteIcon}>Item 1</NavbarItem>
        <NavbarItem icon={OtherIcon}>Item 2</NavbarItem>
        <NavbarItem icon={AnotherIcon}>Item 3</NavbarItem>
      </div>
    </nav>
  );
}

推荐阅读