如何使 React Tabs 组件成为可重用的组件?

How to make React Tabs component as reusable component?

提问人:bv-dev 提问时间:12/13/2022 最后编辑:bv-dev 更新时间:12/13/2022 访问量:756

问:

import { useState } from "react";

export default function TabsComponent() {
    const tabs = [
        { name: "Home", link: "#", content: "Home Content" },
        { name: "About", link: "#", content: "About Content" },
        { name: "Contact", link: "#", content: "Contact Content" },
    ];
    const [openTab, setOpenTab] = useState("Home");

    return (
        <div>
            <div className="container mx-auto">
                <div className="flex flex-col items-center justify-center max-w-xl">
                    <ul className="flex space-x-2">
                        {tabs.map((tab) => (
                            <li key={tab.name}>
                                <a
                                    href={tab.link}
                                    onClick={() => setOpenTab(tab.name)}
                                    className="inline-block px-4 py-2 text-gray-600 bg-white rounded shadow"
                                >
                                    {tab.name}
                                </a>
                            </li>
                        ))}
                    </ul>
                    <div className="p-3 mt-6 bg-white border">
                        {tabs.map((tab) => (
                            <div
                                key={tab.name}
                                className={
                                    tab.name === openTab ? "d-block" : "d-none"
                                }
                            >
                                {tab.content}
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        </div>
    );
}

我是 React 的新手,我希望这个 React Tabs 功能组件是可重用的。如何解构整个组件以在应用程序中的任何位置使用。

我是 React 的新手,我希望这个 React Tabs 功能组件是可重用的。如何解构整个组件以在应用程序中的任何位置使用。

要求

JavaScript ReactJS 前端 解构 React-Tabs

评论

0赞 Andy 12/13/2022
这取决于可重用性,但关键是它在其 props 中接受 tabs 数组,而不是在组件本身中定义它们。
0赞 leo 12/13/2022
您可以将选项卡作为属性传递,并根据属性的索引初始化内部 openTab 状态,以便能够定义哪个应该是默认值。这样,Tabs 组件将只关心呈现您作为属性传递的任何结构。
0赞 Keith 12/13/2022
如上所述,-> 并使用 ->export default function TabsComponent({tabs}) { ..../*tabs is now a prop*/ } <TabsComponent tabs={{ name: "Home", link: .....}} />
0赞 bv-dev 12/13/2022
任何人都可以举例说明吗?
0赞 bv-dev 12/13/2022
@Keith 它不起作用,你能检查一次吗?

答:

0赞 Ali Sattarzadeh 12/13/2022 #1

你做的很棒,只是将标签作为道具传递

喜欢这个:

export default function TabsComponent({tabs}) {
 
  const [openTab, setOpenTab] = useState(tabs[0]);

  return (
    <div>
      <div className="container mx-auto">
        <div className="flex flex-col items-center justify-center max-w-xl">
          <ul className="flex space-x-2">
            {tabs.map((tab) => (
              <li key={tab.name}>
                <a
                  href={tab.link}
                  onClick={() => setOpenTab(tab.name)}
                  className="inline-block px-4 py-2 text-gray-600 bg-white rounded shadow"
                >
                  {tab.name}
                </a>
              </li>
            ))}
          </ul>
          <div className="p-3 mt-6 bg-white border">
            {tabs.map((tab) => (
              <div
                key={tab.name}
                className={
                  tab.name === openTab ? "d-block" : "d-none"
                }
              >
                {tab.content}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

在其他组件中:

   <TabsComponent  tabs={[
        { name: "Home", link: "#", content: "Home Content" },
        { name: "About", link: "#", content: "About Content" },
        { name: "Contact", link: "#", content: "Contact Content" },
      ]} />

如果你想有单独的组件来单独处理它们,你可以将每个部分定义为组件

我做了,你可以在这里看到:https://codesandbox.io/s/material-ui-grid-demo-forked-ob4re4?file=/src/Tab.jsx

评论

0赞 bv-dev 12/13/2022
嗨@Ali Sattarzadeh 感谢您的回答,我想根据我的要求扩展您的答案。我想使用这些选项卡,如下所示。你能更新一下吗?<TabsContainer> <Tabs> <Tab> Tab 1 </Tab> <Tab> Tab 2 </Tab> </Tabs> <div> <TabContent> Tab 内容 1 </TabContent> <TabContent> Tab 内容 2 </TabContent> </div> </TabsContainer>
0赞 Ali Sattarzadeh 12/13/2022
嗨,我不明白 TabsContainer 和 TabContent 等是什么。它们是另一个组件吗?
0赞 bv-dev 12/13/2022
它们不是其他组件,但我想单独导出选项卡和选项卡内容。
0赞 Ali Sattarzadeh 12/13/2022
啊哈,让我为它制作 Codesandbox
0赞 bv-dev 12/13/2022
好的,谢谢!我添加了需求的图像(i.stack.imgur.com/xevCF.png)。请检查此内容以了解更多信息。
0赞 Keith 12/13/2022 #2

有几种方法可以做到这一点。

  1. 只需创建一个名为 tabs 的 prop,然后就可以将 tabs 数组发送到 tabs prop。
export default function TabsComponent({tabs}) {
  //const tabs = ...  no need for this now..
  //rest of code the same
}

//call like
function Home() {
  return <TabsComponent tabs={[
    { name: "Home", link: "#", content: "Home Content" },
    { name: "About", link: "#", content: "About Content" },
    { name: "Contact", link: "#", content: "Contact Content" }
  ]}/>
}
  1. 另一个想法是实际使用隐式道具。children
export default function TabsComponent({children}) {
  //const tabs = ...  no need for this now..
  const tabs = children;
  //rest of code the same
}

//call like
function Home() {
  return <TabsComponent>
  {[
    { name: "Home", link: "#", content: "Home Content" },
    { name: "About", link: "#", content: "About Content" },
    { name: "Contact", link: "#", content: "Contact Content" }
  ]}
  </TabsComponent>;
}
  1. 另一种选择是实际组合您的组件,因此您可以拥有如下所示的内容,但是处理状态等需要更多的工作,因此这不是一个微不足道的更改,但我认为对于可重用性是最好的选择。->
function Home() {
  return <TabsComponent>
     <TabSection name="Home" link="#" default>
        Home Content
     </TabSection>
     <TabSection name="About" link="#">
        About Content
     </TabSection>
     <TabSection name="Contact" link="#">
        Contact Content
     </TabSection>
  </TabsComponent>;
}

我没有展示 option.3 的代码,因为它比传递一些道具要复杂一些,但我认为这是最好的选择,所以如果它感兴趣,请告诉我们。