salivan salivan - 1 month ago 9
React JSX Question

react component iterating over data and maping a complicated row structure

Data looks like this:

const items = [
{ image: "http://loremflickr.com/320/320/sport-car?random=1", title: "BMW 545", price: "6.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=2", title: "Mercedes GL", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=3", title: "Toyota", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=4", title: "Porsche", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=5", title: "VW Golf", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=6", title: "Infinity GS", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=7", title: "Ford GT", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=8", title: "Mitsubishi Lancer", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=9", title: "Fiat Punto", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=10", title: "Pegaout Corsa", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=11", title: "Open Corsa", price: "16.500$" },
{ image: "http://loremflickr.com/320/320/sport-car?random=12", title: "VW Passat", price: "16.500$" }
]


final structure should look like this:

<div className="Grid">
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
</div>
<div className="Grid">
<div className="Grid-cell u-size1of4"><Card/></div>
<div className="Grid-cell u-size2of4"><Card type="double"/></div>
<div className="Grid-cell u-size1of4"><Card/></div>
</div>
<div className="Grid">
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
</div>
<div className="Grid">
<div className="Grid-cell u-size1of4"><Card/></div>
<div className="Grid-cell u-size2of4"><Card type="double"/></div>
<div className="Grid-cell u-size1of4"><Card/></div>
</div>
<div className="Grid">
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
<div className="Grid-cell u-size1of2"><Card type="double"/></div>
</div>


image / title / price can be passed to Card component.

I started by creating a
for
loop, but that thing very soon started to look like a monstrosity of
if/else
.

Is it possible to use
map
for this? or there a better library for handling this kind of templating?

enter image description here

Answer

This should deliver the desired DOM grid: http://codepen.io/PiotrBerebecki/pen/rrdBjX

You would now need to clean the code and apply proper styling.

const items = [
  { image: "http://loremflickr.com/320/320/sport-car?random=1", title: "0 BMW 545", price: "6.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=2", title: "1 Mercedes GL", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=3", title: "2 Toyota", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=4", title: "3 Porsche", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=5", title: "4 VW Golf", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=6", title: "5 Infinity GS", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=7", title: "6 Ford GT", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=8", title: "7 Mitsubishi Lancer", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=9", title: "8 Fiat Punto", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=10", title: "9 Pegaout Corsa", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=11", title: "10 Open Corsa", price: "16.500$" },
  { image: "http://loremflickr.com/320/320/sport-car?random=12", title: "11 VW Passat", price: "16.500$" }
]

class App extends React.Component {
  render() {   
    const GridArrays = {};

    items.forEach((item, index, array) => {
      if (index % 5 === 0) {
        GridArrays[Object.keys(GridArrays).length] = array.slice(index, index + 2);
      } else if (index % 5 === 2) {
        GridArrays[Object.keys(GridArrays).length] = array.slice(index, index + 3);
      }
    });

    const renderGrids = Object.keys(GridArrays).map(key => {
      if (Number(key) % 2 === 0) {
        return <TwoCars cars={GridArrays[key]} />;
      } else {
        return <ThreeCars cars={GridArrays[key]} />;
      }
    });

    return (
      <div>
        {renderGrids}
      </div>
    );
  }
}


class TwoCars extends React.Component {
  render() {   
    const renderTwoCars = this.props.cars.map((car, index) => {
      return (
        <div className="grid-cell u-size1of2">
          {index === 0 ?
            <Card type="double" image={car.image} title={car.title} price={car.price}/>
           :
            <Card type="double" image={car.image} title={car.title} price={car.price}/>
          } 
        </div>
      );
    });  

    return (
      <div className="grid-wrapper">
        {renderTwoCars}
      </div>
    );
  }
}


class ThreeCars extends React.Component {
  render() {   
    const renderThreeCars = this.props.cars.map((car, index) => {
      return (
        <div className={index % 2 === 0 ? "grid-cell u-size1of4" : "grid-cell u-size2of4"}>
         {index === 0 ?
            <Card image={car.image} title={car.title} price={car.price}/>
          : index === 1 ?
            <Card image={car.image} title={car.title} price={car.price} type="double" />
          :
            <Card image={car.image} title={car.title} price={car.price}/>
         }
        </div>
      );
    });  

    return (
      <div className="grid-wrapper">
        {renderThreeCars}
      </div>
    );
  }
}


class Card extends React.Component {
  render() { 
    let styles = this.props.type === 'double' ? 'double' : 'single';

    return (
      <div className={`card-${styles}`}>
        <div className={`image-${styles}`}>
          <img className={`img-${styles}`} src={this.props.image} />
        </div>
        <div className={`desc-${styles}`}>
          <h4>{this.props.title}</h4>
          <p>{this.props.price}</p>
        </div>
      </div>
    );
  }
}


ReactDOM.render(
  <App />,
  document.getElementById('app')
);