reactjschakra-uiconditional-renderinggroq

How can I conditionally render tabs depending on the value of a field of a GROQ query?


I have a GROQ query where the result is an array of documents, of which one of the fields, "fieldName", can contain "a", "b" or "c". If the array contains any with the value "a" then I want to display a Chakra-UI <Tab> for it in the <TabList> as well as a <TabPanel> in the <TabPanels>. If there are none with the value "a", don't display a tab, and repeat this for conditions "b" and "c".

// GROQ query

*[slug.current == $slug]{
    array[]->
}
// GROQ query json response

"result": [
    0:
    "array": [
        0: {...}
        1: {
            "_id": "1"
            "fieldName": "a"
        }
        2: {
            "_id": "2"
            "fieldName": "c"
        }
        3: {...}
        4: {...}
        5: {...}
        ]
    }
]

// This example would return tabs and panels for only a and c

I know how to loop through the items conditionally in the example below, but this doesn't help me with the Tab items as looping through these would give me repeated tabs.

<Tabs>
  <TabList>
    <Tab>A</Tab> // Conditionally render this only if any array items' "fieldName" contains value "a"

    ...

  </TabList>
  <TabPanels>
    <TabPanel>
      {array &&
        array.fieldName.map((panel) => (
          <>{panel.fieldName == "a" ? <>{panel.fieldName}</> : null}</>
        ))}
    </TabPanel>

    ...

  </TabPanels>
</Tabs>

Because of the structure of Chakra-UI's tabs I am stumped how I can do this and would appreciate any help. There must be a better way of doing this than the one I am trying?


Solution

  • You can create a object and use it to check if to show specific tab and tabpanel or not

    import React from 'react';
    import {
      ChakraProvider,
      Tabs,
      TabList,
      TabPanels,
      Tab,
      TabPanel,
    } from '@chakra-ui/react';
    import './style.css';
    
    const arr = [
      {
        _id: '1',
        fieldName: 'a',
      },
      {
        _id: '2',
      },
      {
        _id: '3',
        fieldName: 'c',
      },
      {
        _id: '4',
        fieldName: 'a',
      },
      {
        _id: '5',
        fieldName: 'c',
      },
      {
        _id: '6',
        fieldName: 'e',
      },
      {
        _id: '7',
      },
      {
        _id: '8',
        fieldName: 'c',
      },
      {
        _id: '9',
        fieldName: 'a',
      },
    ];
    
    function process(arr) {
      const tabs = {};
      arr.forEach((item, idx) => {
        if (item.fieldName && !tabs[item.fieldName]) {
          tabs[item.fieldName] = idx;
        }
      });
      return tabs;
    }
    
    export default function App() {
      const tabs = process(arr);
      return (
        <ChakraProvider>
          <Tabs>
            <TabList>
              {tabs['a'] && <Tab>A</Tab>}
              {tabs['b'] && <Tab>B</Tab>}
              {tabs['c'] && <Tab>C</Tab>}
              {tabs['d'] && <Tab>D</Tab>}
              {tabs['e'] && <Tab>E</Tab>}
            </TabList>
    
            <TabPanels>
              {tabs['a'] && (
                <TabPanel>
                  <p>A</p>
                </TabPanel>
              )}
              {tabs['b'] && (
                <TabPanel>
                  <p>B</p>
                </TabPanel>
              )}
              {tabs['c'] && (
                <TabPanel>
                  <p>C</p>
                </TabPanel>
              )}
              {tabs['d'] && (
                <TabPanel>
                  <p>D</p>
                </TabPanel>
              )}
              {tabs['e'] && (
                <TabPanel>
                  <p>E</p>
                </TabPanel>
              )}
            </TabPanels>
          </Tabs>
        </ChakraProvider>
      );
    }
    

    Working Example