ccd
ccd

Reputation: 6908

Rendering react in a conditional for loop

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?

Upvotes: 2

Views: 11017

Answers (5)

spirift
spirift

Reputation: 3062

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>
    );
  }
}

Upvotes: 2

Alex G
Alex G

Reputation: 1917

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>
    );
  }
}

Upvotes: -1

Mayank Shukla
Mayank Shukla

Reputation: 104369

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>
);

Upvotes: 0

Kevin He
Kevin He

Reputation: 1250

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.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074148

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>
    );
  }
}

Upvotes: 1

Related Questions