2

I have a static information in web page.

class MyStaticWebPage extends React.Component {
  render() {
    return (
      <TopContainer>
        <IconListContainer>
          <LeftButton
            Icon={MyIcon1}
            color="#ffffff"
            text="text1"
          />
          <CenterButton
            Icon={MyIcon2}
            color="#eeeeee"
            text="text2"
          />
          <RightButton
            Icon={MyIcon3}
            color="#dddddd"
            text="text3"
          />
        </IconListContainer>
        <IconListContainer>
          <LeftButton
            Icon={MyIcon4}
            color="#cccccc"
            text="text4"
          />
        </IconListContainer>
      </TopContainer>
    );
  }
}

This page is statically display in a row list, per line maximum three icons, and now I want to turn them dynamically, suppose I store icon props in a props array.

[
  {
    icon: 'MyIcon1',
    color: '#ffffff',
    text: 'text1'
  },
  {
    icon: 'MyIcon2',
    color: '#eeeeee',
    text: 'text2'
  },
  {
    icon: 'MyIcon3',
    color: '#dddddd',
    text: 'text3'
  },
  {
    icon: 'MyIcon4',
    color: '#cccccc',
    text: 'text4'
  }
]

Finally make page automatically rendered using this props array.

class MyStaticWebPage extends React.Component {
  render() {
    var rows = []
    for (var i = 0; i <= parseInt(iconNum / 3); i++) {
      // row level for loop
      // rows.push(row)
      for (var j = iconNum; j % 3 !== 0; j--) {
        // icon level for loop
        // rows.push(icon)
      }
    }
    return (
      <TopContainer>
        {rows}
      </TopContainer>
    );
  }
}

How to do with this through realistic react code?

3
  • What specific problem are you having? You seem to be off to a reasonable start, so...keep going. Commented Sep 17, 2018 at 7:45
  • 1
    A couple of side notes, though: 1. Using parseInt on numbers is an anti-pattern. If your goal is to round, use Math.round. If your goal is to floor, use Math.floor. 2. If you start at 0, you go to < the number of items, not <=. Commented Sep 17, 2018 at 7:46
  • The for loop in JSX is much confusing me. Commented Sep 17, 2018 at 7:46

5 Answers 5

2

Given you have a flat array but want to render it in rows of three the first thing you should do is chunk the array. Lodash has a method for this or you can do a simple enough reduce on your array.

const chunkedArray = icons.reduce((reduction, icon, index) => {
  index % 3 ? reduction[reduction.length - 1].push(icon) : reduction.push([icon])
  return reduction
}, [])

Now you have your data in the right shape we can easily map that to output jsx.

class IconListWrapper extends React.Component {
  render() {
    const { subList } = this.props
    const buttonTypes = ['LeftButton', 'CenterButton', 'RightButton']
    const Element = buttonTypes[index]
    return (
      <IconListContainer>
        {subList.map((icon, index) => <Element
            Icon={MyIcon1}
            color="#ffffff"
            text="text1"
          />)}
      </IconListContainer>
    );
  }
}

class MyStaticWebPage extends React.Component {
  render() {
    return (
      <TopContainer>
        {chunkedArray.map((subList) => <IconListWrapper subList={subList} />)}
      </TopContainer>
    );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

I think you're asking how to make sure you group the icons into groups of three using LeftButton, CenterButton, and RightButton.

I'll assume you start with something like this:

var icons = [
  {
    icon: 'MyIcon1',
    color: '#ffffff',
    text: 'text1'
  },
  {
    icon: 'MyIcon2',
    color: '#eeeeee',
    text: 'text2'
  },
  {
    icon: 'MyIcon3',
    color: '#dddddd',
    text: 'text3'
  },
  {
    icon: 'MyIcon4',
    color: '#cccccc',
    text: 'text4'
  }
];

then, see comments:

class MyStaticWebPage extends React.Component {
  var buttonTypes = [LeftButton, CenterButton, RightButton];
  render() {
    var rows = [];
    var children = [];
    for (var i = 0; i < icons.length; i++) {
      // x will be 0, 1, or 2
      var x = i % 3;
      // Get the button type to use
      var buttonType = buttonTypes[x];
      // Create the button using `createElement`
      children.push(React.createElement(buttonType, icons[i]);
      // If this is the last button of three, add these in a container
      // and get a new array for children
      if (x == 2) {
        rows.push(<IconContainer>{children}</IconContianer>);
        children = [];
      }
    }
    // Handle any remaining children
    if (children.length) {
      rows.push(<IconContainer>{children}</IconContianer>);
    }
    return (
      <TopContainer>
        {rows}
      </TopContainer>
    );
  }
}

Comments

0

As pointed out in other answers - the loop can be achieved with map function. To display them dynamically, you may wish to take a look at flexbox and use them in css.

Comments

0

One possible way of writing is like this:

var buttonTypes = [LeftButton, CenterButton, RightButton];

let table = [];
arr.forEach((el, i) => {

  let Component = buttonTypes[i%3];
  rows.push(
    <Component
      Icon={el.icon}
      text={el.text}
      color={el.color}
    />
  )

  if(i%3 == 2) {
    table.push( <IconListContainer> {rows} </IconListContainer> )
    rows = [];
  }
})

if (rows.length) {
  table.push( <IconListContainer> {rows} </IconListContainer> );
}

return (
  <TopContainer>
    {table}
  </TopContainer>
);

Comments

-1

You can try something like this.

const icons = [
  {
    icon: 'MyIcon1',
    color: '#ffffff',
    text: 'text1'
  },
  {
    icon: 'MyIcon2',
    color: '#eeeeee',
    text: 'text2'
  },
  {
    icon: 'MyIcon3',
    color: '#dddddd',
    text: 'text3'
  },
  {
    icon: 'MyIcon4',
    color: '#cccccc',
    text: 'text4'
  }
];

class MyStaticWebPage extends React.Component {

  const menu = [
    ({ icon, color, text }) => (<LeftButton Icon={icon} color={color} text={text} />),
    ({ icon, color, text }) => (<CenterButton Icon={icon} color={color} text={text} />),
    ({ icon, color, text }) => (<RightButton Icon={icon} color={color} text={text} />)
  ];

  render() {
    return (
      <TopContainer>
        <IconListContainer>
          {icons && icons.map((icon, i) => menu[i % 3](icon))}
        </IconListContainer>
      </TopContainer>
    );
  }
}

Comments

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.