Tanzeel
Tanzeel

Reputation: 4998

How to display images in row and column in React

I'm well versed with Angular but not React. I want to display images in a row-col layout in such a way that no. of columns should be dynamic while the no. of rows should be adjusted accordingly. That means if the user gives 4(say) images and says that he wants 2(say) columns, then the grid layout should be 2X2. Pretty simple.

I'm setting the state in App.js

state = {
    flowerCard: [
      {
        colCount: 3,  // <-------------- this will decide number of columns
        tiles: [
          {
            imageSource: '...',
            text: 'White flower',
          },
          {
            imageSource: '...',
            text: 'Red flower',
          },
          {
            imageSource: '...',
            text: 'Purple flower',
          },
          {
            imageSource: '...',
            text: 'Purple flower',
          },
        ],
      },
    ],
  };

  ...
  
  <Card
    colCount={this.state.flowerCard[0].colCount}
    tiles={this.state.flowerCard[0].tiles}>
  </Card>

Card.js

  let localTiles = props.tiles;
  let colCount = props.colCount;
  return (
    <div>
      {localTiles.map((tile, index) => {
        return (
          <div>
            <Row>
              <Col md={4}>
                <p>{tile.text}</p>
                <Image
                  className="tile-image"
                  height={100}
                  width={300}
                  src={tile.imageSource}
                  alt="logo"
                />
              </Col>
            </Row>
          </div>
        );
      })}
    </div>
  );

I've done similar thing in Angular using *ngFor. Please help me achieve this in React. I've created one stackblitz for your ease. please pitch in.

Upvotes: 0

Views: 2781

Answers (1)

HollyOS
HollyOS

Reputation: 407

If you're trying to populate cards in the list, that should be done with .map on an array. It works similarly to ngFor from Angular. So, you've got that piece correct. Where things will get different is by setting the width of your columns. You're going to need to be more reliant upon CSS to get the grid set. Styled components are a nice option since they allow you access to prop values. However, you can also work inline if need be.

  1. Look into CSS Grid or CSS Flexbox for your layout needs.
  2. Set the appropriate width based on the number of columns you'll need:
const StyledCol = styled(Col)`
  width: calc(100% / ${colCount}); /* Dynamically sets the grid column widths based on it's parent container element width */
`;

If you need to maintain px value, in the props, you'll need to figure out the width of the container then just divide that by the number of columns.

const pxWidth = containerPxWidth / colCount;

...

  width={pxWidth}

I would suggest moving the width and height settings to your <Col> instead though. Then you can size the image to 100% (or whatever percentage) of the parent dimensions. This allows for some more flexibility in how you move the children within the given grid space.

Card.js

  // Destructuring for the win
  const { tiles: localTiles, colCount } = props;

  // If you need to have this inline, also need to figure out `containerPxWidth`
  // value based on the width of the `Row`
  const pxWidth = containerPxWidth / colCount;

  return (
    <div>
      {/* You can auto return map with parenthesis */}
      {localTiles.map((tile, index) => (
        <div>
          <Row height={100}>
            <Col md={4} width={pxWidth}>
              <p>{tile.text}</p>
              <Image
                className="tile-image"
                src={tile.imageSource}
                alt="logo"
              />
            </Col>
          </Row>
        </div>
      ))}
    </div>
  );

Upvotes: 1

Related Questions