1

What is the best way to create multiple empty elements inline using React within render in a declarative fashion?

For example, say I wanted 8 empty divs, the following was my first attempt although it doesn't work, is there a better way?

render() {
    return (
        <section>
            {
                new Array(8).map(()=> <div />)
            }
        </section>
    );
}
4
  • 1
    Have you tried it? Does it really create 8 divs? Commented Apr 25, 2019 at 10:03
  • 4
    Array(8).fill(<div />) Commented Apr 25, 2019 at 10:06
  • This is not really a React issue, -> Array(8).map(f => 10), do you think this returns an array with 8 elements with the value 10?,. Unfortunately not, map doesn't iterate empty array elements,. but like @hindmost pointed out Array(8).fill(10), this would. Commented Apr 25, 2019 at 10:11
  • I didn't realise map doesn't iterate empty elements, fill does yeah. Commented Apr 25, 2019 at 10:13

3 Answers 3

4

I'd use a small helper for it:

  const times = (length, fn) => Array.from({ length }, (_, i) => fn(i));

To be used as:

 times(8, i => <div key={i} />)
Sign up to request clarification or add additional context in comments.

3 Comments

This is probably the way I would normally go about it, just wondering if there was a more concise inline method. Is there any advantage to this over using Mike's answer stackoverflow.com/a/55846879/1528308 ?
@alex it's shorter, more readable (imo) and only iterates once (but that doesnt matter for such small arrays). Filling the array just to be able to iterate it with .map makes just little sense to me.
It does seem a little awkward I agree, your divs are missing keys though.
2

You'd have to fill the array first:

export default class Example extends React.Component {
    render() {
        return (
            {Array(8).fill(null).map((item, index) => (
                <div key={index}/>
            )}
        )
    }
}

3 Comments

You don't even need the .fill(null), just fill() will work, this is because map doesn't iterate empty, but it does iterate undefined..
TS expects at least one argument for fill, seems like value isn't optional: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Yes, I'd say TS definition is slightly wrong there. A none passed argument in JS is undefined, and undefined is a totally valid value for fill..
1

As seen the simplest option is just Array(8).fill().map(<div />)

But one issue with the above is your creating an array to make another array. It's not a massive issue, but if you like modern JS, a nice solution is iterators. And of course iterators can be used for other things, not just arrays.

Below is an example.

function *range(r, map) {
  for (let l = 0; l < r; l += 1) yield(map ? map(l) : l);
}

const a1 = Array.from(range(3));
const a2 = Array.from(range(3, m => 2 + m * 2));

console.log(a1);
console.log(a2);

//and of course not just arrays
for (const value of range(3)) console.log(value);

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.