Paul A
Paul A

Reputation: 417

Loop components without array

I have a render in my component that renders out many components and i want it to repeat some of them. The problem I have is when I create an HTML render the variable is not being processed and it is displaying as text.

The actual code contains many more componentsbut I have simplified it

MY code

export default function(props) {
  const bookData = props.bookData;
  const pageStart = props.pageStart;
  // Create Diary HTML
  const myLoop = (loopNumber, pageStart) => {
    let html = '';
    for (let i = 0; i < loopNumber; i++) {
      let singleLoop = `<DiaryByDay loop={${i}} />`;
      html = html + '  ' + singleLoop;
    }
    return html;
  };

const dayByDayPages = myLoop(1, 3);
const dayByDayReturn = <Fragment>  {dayByDayPages}  </Fragment>
console.log(dayByDayReturn)


  return (
    dayByDayReturn
  );
}

This is what it looks like when I run my code enter image description here

Upvotes: 0

Views: 1269

Answers (5)

Sohail Ashraf
Sohail Ashraf

Reputation: 10604

The React is printing the component as string because you are saving component as string.

You could store the component in array and then render it.

Try this.

export default function(props) {
    const bookData = props.bookData;
    const pageStart = props.pageStart;
    // Create Diary HTML
    const myLoop = (loopNumber, pageStart) => {
      let html = [];
     for (let i = loopNumber; i < pageStart; i++) {
        let singleLoop = <DiaryByDay loop={${i}} />;
        html.push(singleLoop);
      }
      return html;
    };
  const dayByDayPages = myLoop(1, 3);
  const dayByDayReturn = <Fragment> {dayByDayPages}  </Fragment>


    return (
      dayByDayReturn
    );
  }

Codesandbox Example:

Edit Loop components without array

Upvotes: 1

Fraction
Fraction

Reputation: 12974

You must return an array of elements:

const myLoop = (loopNumber, pageStart) => {
  return [...Array(loopNumber).keys()].map(v => <DiaryByDay key={v} loop={v} />);
};

Or

const myLoop = (loopNumber, pageStart) => {
    const html = [];
    for (let i = 0; i < loopNumber; i++) {
      html.push(<DiaryByDay key={i} loop={i} />);
    }
    return html;
  };

Demo:

const Fragment = React.Fragment;

function DiaryByDay(props) {
  return <div>DiaryByDay {props.loop}</div>
}

function App(props) {
  //const bookData = props.bookData;
  //const pageStart = props.pageStart;
  // Create Diary HTML
  const myLoop = (loopNumber, pageStart) => {
    return [...Array(loopNumber).keys()].map(v => <DiaryByDay key={v} loop={v} />);
  };

const dayByDayPages = myLoop(4, 3);
const dayByDayReturn = <Fragment>  {dayByDayPages}  </Fragment>
//console.log(dayByDayReturn)


  return (
    dayByDayReturn
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 1

Vengleab SO
Vengleab SO

Reputation: 814

You should use JSX element as return type

export default function(props) {
  const bookData = props.bookData;
  const pageStart = props.pageStart;
  // Create Diary HTML
  const myLoop = (loopNumber, pageStart) => {
    return [...new Array(loopNumber)].map(i => <DiaryByDay loop={i} />);
  };

  const dayByDayPages = myLoop(1, 3);
  const dayByDayReturn = <Fragment> {dayByDayPages} </Fragment>;
  console.log(dayByDayReturn);
  return dayByDayReturn;
}

Upvotes: 1

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

Change your function so that it returns an array:

 const myLoop = (loopNumber, pageStart) => {
    let html = [];
    for (let i = 0; i < loopNumber; i++) {
      let singleLoop = <DiaryByDay loop={i} />;
      html.push(singleLoop);
    }
    return html;
  };

If you return a huge string obviously it'll try to display the string.

And you should also add a key prop to each DiaryByDay component. Using index value might not be a good idea for that because if you later delete some elements in your array the indexes change.

So let singleLoop = <DiaryByDay loop={i} />;

should be

let singleLoop = <DiaryByDay key={ ...something unique for each element} loop={i} />;

Upvotes: 1

hiddenuser.2524
hiddenuser.2524

Reputation: 4988

You are appending strings, not React elements. You need to append to an array:

export default function(props) {
  const bookData = props.bookData;
  const pageStart = props.pageStart;
  // Create Diary HTML
  const myLoop = (loopNumber, pageStart) => {
    const elements = [];
    for (let i = 0; i < loopNumber; i++) {
      elements.push(<DiaryByDay loop={i} key={i} />);
    }
    return elements;
  };

  const dayByDayPages = myLoop(3, 3);
  const dayByDayReturn = <> {dayByDayPages} </>;

  return dayByDayReturn;
}

Upvotes: 1

Related Questions