Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tabs] Using fragments in Tabs child node breaks functionality #30153

Closed
2 tasks done
aliyeysides opened this issue Dec 11, 2021 · 10 comments
Closed
2 tasks done

[Tabs] Using fragments in Tabs child node breaks functionality #30153

aliyeysides opened this issue Dec 11, 2021 · 10 comments
Labels
component: tabs This is the name of the generic UI component, not the React module! status: expected behavior Does not imply the behavior is intended. Just that we know about it and can't work around it

Comments

@aliyeysides
Copy link

aliyeysides commented Dec 11, 2021

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 馃槸

Functional component child nodes of Tabs wrapped in fragments break functionality. For example, if I have a custom functional component <DynamicTabs /> that returns multiple Tab elements with a fragment root and use <DynamicTabs /> as a child of Tabs, it seems to break the functionality. If I don't use fragments here then I get a TS error for returning an array of elements, and replacing the fragment root with a div or span also does not work:

function DynamicTabs() {
  const arr = [0, 1, 2];
  return (
    <>
      {arr.map((n) => (
        <Tab label={`${n}`} {...a11yProps(n)} />
      ))}
    </>
  );
}
        <Tabs
          value={value}
          onChange={handleChange}
          aria-label="basic tabs example"
        >
          <DynamicTabs /> // can't do this :[ 
        </Tabs>

Expected behavior 馃

The expected behavior is that functional components that return an element with a fragment root don't break Tabs functionality when transcluded into <Tabs>.

For a workaround, I could just avoid using a custom functional component and instead do something inline, but I would ideally like to avoid the code below:

<Tabs
  value={value}
  onChange={handleChange}
  aria-label="basic tabs example"
>
    {arr.map((n) => (
       <Tab label={`${n}`} {...a11yProps(n)} />
    ))}
</Tabs>

Steps to reproduce 馃暪

codesandbox: https://codesandbox.io/s/basictabs-material-demo-forked-cbze4?file=/demo.tsx:1310-1475

Steps:

  1. Click on the tabs in the codebox browser and you should see that it doesn't work as expected.
  2. Replace the DynamicTabs component with the inline approach above and you should see it working.

Context 馃敠

Using fragments should not break the Tab functionality. Using functional components wrapped in fragments works for TabPanel, but not for children of Tabs. This forces me to use the inline method which hurts readability and consistency. This may or may not be related to: #27947

Your environment 馃寧

`npx @mui/envinfo`
 Broswer: Chrome Version 96.0.4664.93 (Official Build) (x86_64)
  System:
    OS: macOS 11.3.1
  Binaries:
    Node: 14.16.1 - ~/.nvm/versions/node/v14.16.1/bin/node
    Yarn: 1.22.5 - ~/.yarn/bin/yarn
    npm: 6.14.12 - ~/.nvm/versions/node/v14.16.1/bin/npm
  Browsers:
    Chrome: 96.0.4664.93
    Edge: Not Found
    Firefox: Not Found
    Safari: 14.1
  npmPackages:
    @emotion/react: ^11.5.0 => 11.5.0 
    @emotion/styled: ^11.3.0 => 11.3.0 
    @mui/core:  5.0.0-alpha.54 
    @mui/icons-material: ^5.1.0 => 5.1.0 
    @mui/material: ^5.1.0 => 5.1.0 
    @mui/private-theming:  5.1.0 
    @mui/styled-engine:  5.1.0 
    @mui/system: ^5.1.0 => 5.1.0 
    @mui/types:  7.1.0 
    @mui/utils:  5.1.0 
    @types/react: ^17.0.0 => 17.0.34 
    react: ^17.0.2 => 17.0.2 
    react-dom: ^17.0.2 => 17.0.2 
    typescript: ^4.1.2 => 4.4.4 
@aliyeysides aliyeysides added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 11, 2021
@aliyeysides aliyeysides changed the title [Tabs] Using fragments in Tabs child breaks functionality [Tabs] Using fragments in Tabs child node breaks functionality Dec 11, 2021
@michaldudak
Copy link
Member

The Tabs component requires Tab components as direct children.
If you'd like to extract the logic of rendering individual tabs, you can create a function (not a functional component) that returns the array: https://codesandbox.io/s/basictabs-material-demo-forked-pi4p3?file=/demo.tsx

@michaldudak michaldudak added component: tabs This is the name of the generic UI component, not the React module! status: expected behavior Does not imply the behavior is intended. Just that we know about it and can't work around it and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 17, 2021
@Nyctophiliac1918
Copy link

@michaldudak this is not working if I want to render some more things in the tab, like icon+text using the component property of Tab. It still makes it a single tab if I use a map to render the data in tabs.

@Nyctophiliac1918
Copy link

@michaldudak Can you please open this issue again?

@michaldudak
Copy link
Member

Please create a codesandbox showing the issue you're facing.

@Nyctophiliac1918
Copy link

On stack overflow, I saw to use the component property to add custom text to tabs. But it is not working.
https://codesandbox.io/s/basictabs-material-demo-forked-jewk6u?file=/demo.tsx:951-990

@jacobsickels
Copy link

@Nyctophiliac1918 I found that forwarding the ref if you want to use the component property works here's the sandbox.
https://codesandbox.io/s/basictabs-material-demo-forked-0gktsy?file=/demo.tsx

@Nyctophiliac1918
Copy link

Thank you so much @jacobsickels!

@manulera
Copy link

Hi @jacobsickels, I have a slightly similar problem, in this case I would like to create a custom element that returns the tab to remove some of the boilerplate, but I cannot use the custom element, it only works if I call it as a function:

// This works
{CustomTab2()}
// This does not
<CustomTab3 />

https://codesandbox.io/s/basictabs-material-demo-forked-ym2g53?file=/demo.tsx

Do I need to pass the ref in some way?

@jacobsickels
Copy link

@manulera I think what you want works if you spread in the props for your CustomTab3

https://codesandbox.io/s/basictabs-material-demo-forked-wg97pd?file=/demo.tsx

@manulera
Copy link

Well that was fast! Thank you so much, it works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: tabs This is the name of the generic UI component, not the React module! status: expected behavior Does not imply the behavior is intended. Just that we know about it and can't work around it
Projects
None yet
Development

No branches or pull requests

5 participants