Zain763
Zain763

Reputation: 77

How do I render nth columns on every row using React JS?

I want to render 4 divs (with class .col-4) in every row div in React JS.

This is what I've already tried:

 return (
    <Styles>
    <div className="container add-page">
      <input className="add-movie container" type="text" placeholder="Search for movies" value={query} onChange={onChange} />
      </div>
      {results.length > 0 && (
         results.map((movie) => (
         
             if(rows%4===0){
              <div className="row">
                <ResultCard movie={movie} key={movie.id} /> 
               
             }
             rows++;
             if(rows%columns===0){
            </div>}
      
        ))
      )}

    </Styles>
  )

But, I'm getting an unexpected token error in the line where I am using if statement. I guess it's got something to do with the JSX syntax.

This is the what the ResultCard Component's return looks like:

return (
    <React.Fragment>
      <Styles>
        {movie.poster_path ? (
          <div className="col-4">
            <img
              src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`}
              alt={`${movie.title} Poster`}
              height="300"
              width="200"
            />

            <Button variant="success">Add to Watchlist</Button>
          </div>
        ) : (
          <div className="col-4">
            <img
              src={NotFound}
              height="300"
              width="200"
              alt="Poster not found"
            />
          </div>
        )}
      </Styles>
    </React.Fragment>
  );

Basically, I want to have a row div and render 4 ResultCard Components in that row div. Then, I want to create another row div for other 4 ResultCard Components and so on and so forth.

P.S: I know there are a few similar questions on this site, but in those questions, the OPs' code was structured in such a way that the answers to those questions solved their problems but are not working for me. That's why I'm asking this here.

Upvotes: 3

Views: 1811

Answers (2)

Ori Drori
Ori Drori

Reputation: 192507

React JSX is not HTML, and it's not a string either. It's translated directly to JS. So you can'y render an opening tag, render a bunch of items, and then close the tag.

You'll have to render the container, and then render the items inside it. To do so you'll need to split (chunk) the results array to sub-arrays, render the .row container, and then map the items inside it.

To chunk the items, you can use Array.from() with Array.slice():

const Demo = ({ results }) => (
  <div>
  {results.length > 0 && (
    Array.from({ length: Math.ceil(results.length / 4) }, (_, i) => (
      <div className="row" key={`row${i}`}>
      {
        results.slice(i * 4, (i + 1) * 4)
          .map((movie) => (
            <div className="card" key={movie}>{movie}</div>
          ))
      }
      </div>
    ))
  )}
  </div>
)

const movies = ['A1', 'B1', 'C1', 'D1', 'A2', 'B2', 'C2', 'D2', 'A3', 'B3', 'C3', 'D3', 'A4', 'B4', 'C4', 'D4'];

ReactDOM.render(
  <Demo results={movies} />,
  root
);
.row {
  display: flex;
  justify-content: space-between;
  border-bottom: 2px solid gold;
}

.card {
  width: 24%;
  background: silver;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

A simpler option, that will save you the need to manipulate the arrays, is to render all the items as a list, and display them using CSS grid:

const Demo = ({ results }) => (
  <div className="grid">
  {results.length > 0 && (
    results.map((movie) => (
      <div className="card" key={movie}>{movie}</div>
    ))
  )}
  </div>
)

const movies = ['A1', 'B1', 'C1', 'D1', 'A2', 'B2', 'C2', 'D2', 'A3', 'B3', 'C3', 'D3', 'A4', 'B4', 'C4', 'D4'];

ReactDOM.render(
  <Demo results={movies} />,
  root
);
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 2px;
}

.card {
  background: silver;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

Upvotes: 5

Lygis
Lygis

Reputation: 100

U cant have if statements inside of jsx, so have your map function outside of return and then just put what u want to return {mapMovies}


const mapMovies = results.length > 0 && (
         results.map((movie) => (
         
             if(rows%4===0){
              <div className="row">
                <ResultCard movie={movie} key={movie.id} /> 
               

             rows++;
             if(rows%columns===0){ %>

Upvotes: 0

Related Questions