0

How do you deal with conditional within a loop in reactjsx where I want to create a <div> and closing </div> every so often so I can create rows

Right now I have something like this:

renderContent = () => {
  const { classes, product } = this.props;

  if (!product) {
    return (
      <>
        <Content />
        <Space width="10px" />
        <Content />
        <Space width="10px" />
        <Content />
        <Space width="10px" />
        <Content />
        <Space width="10px" />
        <Content />
      </>
    );
  }

  const sizeLength = product.length;
  const content = [];

  for (let i = 0; i < sizeLength; i++) {
    if (i === 0 || i % 5) content.push(<div>)

    content.push(
      <Fragment key={`${i}`}>
        <Content />
        <Space width="10px" />
      </Fragment>,
    );

    if (i === 4 || i % 4 ) content.push(</div>)
  }
  return content;
}

So the code renders 5 <Content /> if product is null. This is all in one row.

What I'm trying to accomplish is to have something like this:

<div>
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
</div>

A wrapping every 5 loop, so if there's a 6th, it would be someting like this:

<div>
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
  <Space width="10px" />
  <Content />
</div>
<div>
  <Content />
</div>

But the code I have is breaking and doesn't work. Is there something I'm missing? I'm not sure if the content.push is correct, perhaps there's a better way of dealing with this?

2 Answers 2

1

Put the items in a buffer array, then flush them into a div every 5 items and add that div to the rendering array

  const content = [];
  let buffer = [];
  for (let i = 0; i < sizeLength; i++) {
    buffer.push(
      <Fragment key={`${i}`}>
        <Content />
        <Space width="10px" />
      </Fragment>,
    );
    if (i % 5) {
      content.push(<div>{buffer}</div>);
      buffer = [];
    }
  }
  // one last push if there are left over items
  if (buffer.length > 0) content.push(<div>{buffer}</div>);

  return content;

Sign up to request clarification or add additional context in comments.

2 Comments

I'm going to approve this answer. I appreciate the help. This didn't exactly give me the result I wanted, but it did give me the direction on what to take, thanks!
@hellomello ok, if you get to a solution post the answer and accept it so people know how to do what you really wanted to accomplish
1

In React JSX, you can't have standalone tags like <div> or </div>. Tags define React elements and must always be self-closing or come in pairs with 0 or more elements in between. For example:

// OK - self closing tag. Creates a React div element with no children
const a = <div />;

// OK - Same as above
const b = <div></div>;

// OK - Creates div element with one child, a br element
const c = <div>
  <br />
</div>;

// OK - Creates a div element and executes JS in the braces
// to create two img children
const d = <div>{
  [<img />, <img />]
}</div>;

// Not OK - Everything between the div tags is treated as text (i.e. `; const e = `)
const d = <div>;
const e = </div>;

As you can see in your code, you are pushing standalone tags into your array which is not OK. Instead, use nested loops and nest the element arrays:

const content = [];
const productLength = product.length || 5;

for (let i = 0; i < productLength; i += 5) {
  const innerContent = [];
  const innerLength = Math.min(5, (productLength - i));
  for (let j = 0; j < innerLength; j++) {
    innerContent.push(
      <Fragment key={i+j}>
        <Content />        
        {
          // Don't render the last space. React ignores null children
          j !== innerLength - 1 ? <Space width="10px" /> : null
        }
      </Fragment>
    );
  }

  content.push(<div>{innerContent}</div>);
}

return content;

It's generally a bad idea to use indices as element keys, so prefer to use an ID that you have on your product object, e.g. key={product[i+j].id}

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.