简体   繁体   中英

How to make React Tabs component as reusable component?

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>
    );
}

I'm new to React, I want this React Tabs functional component to be reusable. How to de-structure this entire component to use everywhere in the app.

I'm new to React, I want this React Tabs functional component to be reusable. How to de-structure this entire component to use everywhere in the app.

requirement

What you did is great, just pass tabs as props

like this:

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>
  );
}

and in other component:

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

and if you want to have seperated component to handle them sepratly you can define each part as compnent

I did sth you can see here: https://codesandbox.io/s/material-ui-grid-demo-forked-ob4re4?file=/src/Tab.jsx

There are a couple of ways of doing this.

  1. Just create a prop called tabs, and you can then send the tabs array to the 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. Another idea, is to actually use the implicit children prop.
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. Another option is to actually compose your components, so you could have something like below, but there is a little bit more work required for handling state etc so not a trivial change, but for re-usability I believe is the nicest option. ->
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>;
}

I've not shown the code for option.3, as it's a tad more involved than just passing some props, but I think it's is the nicest option, so let us know if it's of interest.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM