1

I'm working on menu component storybook where i have mapped icon & text , problem is i have horizontal divider in between , how do i Map it with icons & text.From below code i'm getting divider at the bottom of the Menu. I'm trying to achieve as it is in the image. In the storybook i have to map few menu variants as in mui, for that i cannot hardcode divider, if there is any way i can manage it with Map or any other method. Thanks.

enter image description here

 export const Menu= ({ icons }) => {
    return (
        <Paper sx={{ width: 320, maxWidth: '100%' }} >

            <MenuList>
                {icons.map((item) => (
                    <MenuItem>
                        <ListItemIcon fontSize="small">{item.icon}</ListItemIcon>
                        <ListItemText>{item.label}</ListItemText>
                        <Typography variant="body2" color="text.secondary">{item.typography}</Typography>
                    </MenuItem>
                ))}
                <Divider /> /* how do i map this */
            </MenuList>
        </Paper >
    );
}

Stories.js

icons: [
        { icon: <ContentCut fontSize="small" />, typography: "⌘X", label: "Cut" },
        { icon: <ContentCopy fontSize="small" />, typography: "⌘C", label: "Copy" },       
    ]
user3448925
  • 199
  • 1
  • 10
  • Hello there to make sure i understand you correctly , you want to map over `````` as Material UI icons are imported that way am i correct ? , i never really used ```.map()``` method to map over components i usually use it to map over properties Like this example ```function HomeIcon(props) { return ( ); }``` Where we can map over the colors props not the home icon itself check the docs https://mui.com/material-ui/icons/#svgicon , are you able to use a different icon library? – Omar Zeinhom Oct 12 '22 at 15:55
  • 1
    yeah, i'm working on storybook , where user can change the data according to their requirement. so wanted to map divider same as i did for icons & label. If i hardcode like above , i'm getting divider at the end of menu. Thanks – user3448925 Oct 12 '22 at 16:38
  • Your most welcome , may i ask you did my sandbox include everything and answered your question? – Omar Zeinhom Oct 12 '22 at 16:46
  • Where's the image ? – Nidhi Dadiya Oct 14 '22 at 11:10
  • was correcting forgot to add it again.Added it, – user3448925 Oct 14 '22 at 11:13

1 Answers1

2

Answer: If you want the divider to be just one then don't map over it . thats the purpose of the .map() method. and To Acheive the required results i just removed <Menu></Menu> Component and Just Kept the <Papper></Papper> Component

Notes :

  1. In terms of how to Map the Divider with the below example ,you can just wrap it in a empty react fragment<></> and map over the <MenuItem></MenuItem> .

  2. Only issue is that youll get an error in your key props which will say its not unique it can be fixed by assigning index key like the example below and wrap the <MenuItem></MenuItem> Component in It. However thats not best practice ,

  3. <React.Fragment></React.Fragment> Is better practice according to Keyed Fragment React 18 Docs to add a key prop However that's giving a New Error in MUI.

  4. Thats not an issue since were mapping over the MenuItem Component , However if we use for example in @Nathan Comments <React.Fragment key={index}></React.Fragment> or my previous answer to use <></> we would be mapping over the React.Fragment Itself or the empty fragment and would get a new error MUI: The Menu component doesn't accept a Fragment as a child. Uncomment the Examples in the Sandbox Check the sandbox console.

Check Code Code SandBox

Solution


         export const MenuIcon = ({ menuicons }) => {
                return (
             <Paper sx={{ width: 320, maxWidth: "100%" }}>
      {menuicons.map((item, index) => (
        <MenuItem key={item + index}>
          <ListItemIcon fontSize="small">{item.icon}</ListItemIcon>
          <ListItemText>{item.label}</ListItemText>
    
          <Typography variant="body2" color="text.secondary">
            {item.typography}
          </Typography>
        </MenuItem>
      ))}
    
      <Divider />
      <ListItemIcon fontSize="small">
        ClipBoard <ContentCopyIcon fontSize="small" />
      </ListItemIcon>
    </Paper>
                );
            }
    

enter image description here

References

Empty Fragment Syntax React Docs

Stack OverFlow Question MUI Icons - as props

.map() method Syntax - MDN Docs

Omar Zeinhom
  • 125
  • 7
  • 1
    i'm getting horizontal divider below each row. As i want only one as shared the image . thanks – user3448925 Oct 12 '22 at 16:45
  • Ok sorry didnt get you the first time! – Omar Zeinhom Oct 12 '22 at 16:47
  • I'm trying to achieve as it is in material UI . shared the image , as per your we are bit close .Please help. Thanks – user3448925 Oct 12 '22 at 16:53
  • No Problem At all mate trying my best here you can check https://mui.com/material-ui/react-divider/#main-content to check for a solution with me i am just currently trying to adapt my existing sandbox for your requirement – Omar Zeinhom Oct 12 '22 at 16:59
  • Updated my answer check it out now if that suits your requirements!!! – Omar Zeinhom Oct 12 '22 at 17:11
  • 1
    No, its not working. If i add 2 more rows to menu. divider is after each row. – user3448925 Oct 12 '22 at 17:21
  • you want the divider just for the clipboard , then dont map over it thats the purpose of ```.map()``` method btw Check the code sandbox and answer now. – Omar Zeinhom Oct 12 '22 at 17:35
  • means it cannot be achieved with mapping ? Thanks for the answer, if that is the ultimate solution :) – user3448925 Oct 12 '22 at 17:40
  • no man its not that its used to map over and iterate over values not single values https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map Check MDN Docs and Btw their is no ultimate solution man this is meant just to help your reach your questions solution not an ultimate answer if your not satisifed with the answer i am just a user at the end of the day i could just remove my answer for other people to do so , no hard feelings i am just trying to help :) – Omar Zeinhom Oct 12 '22 at 17:43
  • 1
    I didnt mean to offend you. I apologize if i did so. I'm really grateful for your time & answers you provided. Thanks a lot. – user3448925 Oct 12 '22 at 17:45
  • No Problem at all do you want me to remove my answer mate so other people could see it as unanswered ? therefore you'll get other answers , here is another tip using .map with single values ```Using parseInt() with map()``` try it but it does bring undesired and weird behavior to mapping. – Omar Zeinhom Oct 12 '22 at 17:46
  • 1
    no , i'll go with your last answer , i'll remove clipboard from mapping. it really did help me . Thanks – user3448925 Oct 12 '22 at 17:48
  • no problem at all mate , love and peace to you and good luck on your project !!! – Omar Zeinhom Oct 12 '22 at 17:48
  • 1
    fyi for anyone reading this, you can't add key to an empty fragment `<>`, but you *can* add it to a `React.Fragment`, e.g., ``. See [here](https://stackoverflow.com/a/59390967/954986) for details. – Nathan Oct 13 '22 at 06:11
  • Will update will my answer accordingly thank you ! <3 – Omar Zeinhom Oct 14 '22 at 16:41
  • unfortunately for MUI you cant assign a `````` Or ```<>>``` you gell get a new ERROR ```MUI: The Menu component doesn't accept a Fragment as a child.``` Ill Update my Answer accordingly – Omar Zeinhom Oct 14 '22 at 17:11