0

I have created a mega menu where the values will be dynamic (coming from the API). So you never know how many links will be there. But for testing purpose I've put 50 texts in array menu and trying to loop over that so that it look Like this . So there's a parent row and inside that there are 5 columns, each containing 5 links. Per row will contain 5 columns or 25 links.

JSX

const menu = [
  "one",
  "two",
  "three",
  "four",
  "five",
  "one",
  "two",
  "three",
  "four",
  "five",
 ... (total 50)
];

           <Box className={classes.rows}>
              <Box className={classes.cols}>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
              </Box>
              <Box className={classes.cols}>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
              </Box>
              <Box className={classes.cols}>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
              </Box>
              <Box className={classes.cols}>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
              </Box>
              <Box className={classes.cols}>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
                <Typography variant="body1" className={classes.link}>
                  Link 1
                </Typography>
              </Box>
            </Box>

I tried using for loop and then create another 2D array. And later planned to map through that array inside JSX.

 let links = [];

  if (menu.length != 0) {
    for (let i = 0; i < menu.length; i++) {
      for (let j = 0; j < 5; j++) {
        links.push(menu[i]);
      }
    }
  }

But it won't work I know. Can anyone help me with this?

2
  • If you don't know how many links there will be then how do you want the layout of the buttons to change when there is less/more? If there are only 5 links will there be 5 columns with 1 row or 5 rows with 1 column? What if there is an uneven number of links? I think the easiest way to format it is to use flexbox with flexwrap Commented Apr 7, 2022 at 3:42
  • Yes I don't know how many links will be there but there will be atleast 25...that's why I've used this layout. If there are 5 links that will be only one row with one column. even if there are uneven number of links the format will follow this pattern. @coot3 Commented Apr 7, 2022 at 3:52

2 Answers 2

1

First you have to divide your links up into groups of 5. Each group of 5 links will be put in a box with a defined width of 20% (or just under to allow for padding/margins, this will give 5 columns per page).

Then use flexbox with flexwrap: 'wrap' to handle your dynamic links and map your group boxes into that.

Here is an example:

https://codesandbox.io/s/youthful-chaum-83m4vl?file=/src/App.js

import { Box, Typography } from "@mui/material";
import "./styles.css";

const links = [...];

export default function App() {
  // how many groups of 5 given the length of the links array
  const numberOfGroups =
    Math.floor(links.length / 5) + (links.length % 5 > 0 ? 1 : 0);

  const linkGroups = [];

  for (let index = 0; index < numberOfGroups; index++) {
    // push each group of 5 into the linkGroups array
    linkGroups.push(links.slice(index * 5, (index + 1) * 5));
  }

  return (
    <div className="App">
      <Box
        sx={{
          display: "flex",
          width: "100vw",
          flexWrap: "wrap",
          backgroundColor: "lightgrey"
        }}
      >
        {linkGroups.map((linkGroup) => (
          <Box
            sx={{
              width: "18%",
              mb: "16px",
              borderRight: "1px solid white"
            }}
          >
            {linkGroup.map((link) => {
              return <Typography>{link}</Typography>;
            })}
          </Box>
        ))}
      </Box>
    </div>
  );
}

Sign up to request clarification or add additional context in comments.

Comments

1

Not sure if this is what you are after but the code below:

function Row() {
  return (
    <div className="row">
      <p>Link</p>
    </div>
  );
}

const Column = ({ numberOfRows }) => {
  const rows = [];
  for (var i = 0; i < numberOfRows; i++) {
    rows.push(<Row key={i} />);
  }

  return (
    <div className="column">
      <div>Column</div>
      <div>{rows}</div>
    </div>
  );
};

function App() {
  const mockedNumberOfReturnedMenuItems = 28
  const menu = Array.from({ length: mockedNumberOfReturnedMenuItems }, (v, i) => i + 1);
  const maxItemsPerRow = 5;
  const totalNumberOfColumnsRequiredRoundedDown = Math.floor(menu.length / maxItemsPerRow);
  const totalNumberOfMenuItemsDividedByMaxItemsHasRemainder = menu.length % maxItemsPerRow;
  const columnCount = totalNumberOfColumnsRequiredRoundedDown + (totalNumberOfMenuItemsDividedByMaxItemsHasRemainder ? 1 : 0);
  const columns = [];

  for (var i = 0; i < columnCount; i++) {
    var rowCount =
      i + 1 != columnCount ? maxItemsPerRow : menu.length % maxItemsPerRow;
    columns.push(<Column key={i} numberOfRows={rowCount} />);
  }

  return <div>{columns}</div>;
}

Produces this

enter image description here

2 Comments

did you add any additional styling? I'm getting one column only
@buzz yes just a simple float left and some padding on the column.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.