0

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

2
  • Could you please make a reproducible example to show what you are actually getting? Commented Mar 4, 2020 at 9:57
  • 1
    That's normal, you should return an array not a string. Commented Mar 4, 2020 at 10:03

5 Answers 5

1

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;
}
Sign up to request clarification or add additional context in comments.

Comments

1

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;
}

Comments

1

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} />;

Comments

1

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>

Comments

1

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

3 Comments

THanks - but I tried it and got "ReferenceError: can't access lexical declaration `dayByDayReturn' before initialization"
It is still being seen as a text string. The compnent is just rendering "<DiaryByDay loop={0} />" as text on the page
I have updated the code and added a codeSandbox example too.

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.