reactjstypescriptchakra-ui

Can I pass a child component as a prop from the parent. And then have it pass onto futher set children?


I might be doing this completely wrong, but here goes. I'm using the Tabs from Chakra as part of the navigation on my webapp. I'm currently manually writing the names on each Tab, and then calling the component. Each return in the individual components is wrapped in a TabPanel.

function TabNav(){
    return(<Tabs variant='soft-rounded' colorScheme='green'>
    <TabList>
      <Tab>Report</Tab>
      <Tab>FoodItems</Tab>
      <Tab>Incident</Tab>
      <Tab>FormSubmit</Tab>
  
    </TabList>
  
    <TabPanels>
      
        <Report/>
        <FoodItems/>
        <Incident/>
        <TabPanel>
        <SubmitReport/>
        </TabPanel>

  </TabPanels>

</Tabs>

This works, but it doesn't neither scalable, modular and it will be hopeless to keep track off. Is there a way where I can pass the components as props to the , or is there a different way to go about it? I wanted it to be called once, then rendered both in the Tab and TabPanel With pseudo code something like this


import { foodItems, Report, Incident, SubmitReport } "from file"

<Tabs variant='soft-rounded' colorScheme='green'>
    <TabList>
      <Tab "<Report/>">Report.title</Tab>
      <Tab "<FoodItems/>">FoodItems.title/></Tab>
      <Tab "<Incident/>">Incident.title</Tab>
      <Tab "<SubmitReport/>">SubmitReport.title</Tab>
  
    </TabList>
         
    <TabPanels>
    
        <TabPanel>
            Report.render
        </TabPanel>

        <TabPanel>
            FoodItems.render
        </TabPanel>
            Incident.render        
         <TabPanel>
            SubmitReport.render        
        </TabPanel>

<TabPanel>
        
        </TabPanel>
  </TabPanels>

</Tabs>

Sorry for the lack of formal structure. But I can't really describe it any better

I really don't know what to google or try for this one


Solution

  • If I understood correctly, you're trying to find a way to make adding/removing items from your Tabs component in a better way, right?

    One thing you could do is, pass an array of objects with a title and component props that could be used to render the children of TabList and TabPanels dynamically.

    Something like this?

    1. Define an options array somewhere in the parent of TabNav:
    const options = [
      { id: 'report', title: 'Report', component: <Report /> },
      { id: 'food_items', title: 'Food Items', component: <FoodItems /> },
      { id: 'incident', title: 'Incident', component: <Incident /> },
      { id: 'submit_report', title: 'Submit Report', component: <SubmitReport /> },
    ] // pass this to TabNav as props from the parent.
    
    1. Refactor your TabNav component to use this options array to render your components.
    function TabNav({ options }) {
      return(
        <Tabs variant='soft-rounded' colorScheme='green'>
          <TabList>
            {
              options.map((item) => (
                <Tab key={item.id}>{item.title}</Tab>
              )
            }
          </TabList>
      
          <TabPanels>
            {
              options.map((item) => (
                <TabPanel key={item.id}>{item.component}</TabPanel>
              )
            }
          </TabPanels>
        </Tabs>
      );
    }
    

    The benefit of doing this is that you're delegating the logic of how to render your tabs to TabNav while keeping the content itself to be decided by whoever uses TabNav.