Why is a span tag needed inside of this array mapping? (see >>)
const asciiArray = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'];
const gridWidth = 4;
const AsciiGrid = () => (
<div style={{ backgroundColor: 'black', color: 'white', fontFamily: 'monospace' }}>
{Array.from({ length: Math.ceil(asciiArray.length / gridWidth) }, (_, i) => i).map(i => (
<div key={i}>
{asciiArray.slice(i * gridWidth, i * gridWidth + gridWidth).map((char, j) => (
>> <span key={j}>{char}</span>
))}
</div>
))}
</div>
);
If I remove it and just leave {char}, React gives an error of:
Objects are not valid as a React child.
If I leave just {{char}}, I get an unexpected token error.
>Solution :
In React, inside JSX, once your code is inside { braces } it becomes vanilla Javascript. When you say {char} – this is not JSX interpolating the variable char into the template. Instead, it’s vanilla Javascript shorthand for {char: char}. This is also happening because you are accidentally invoking fat arrow function return shorthand syntax.
Because {arr.map(x => ({x}))}, specifically a parenthesis followed by an open curly brace, is the fat arrow function shorthand for "return an object".
const a = (x) => ({x})
specifically ({...}) means "return an object without requiring an explicit return statement".
It’s also invoking the shorthand {x} in Javascript which means create a key named x with the value set to the contents of variable x, aka {x: x}.
Also React can’t render objects as children. <div>{{x: 1}}</div> will cause an error. Note this is the object {x: 1} inside JSX interpolation { brackets }.
You can do
{asciiArray.slice(i * gridWidth, i * gridWidth + gridWidth).map((char, j) => (
char
))}
(note no wrapping { }) but it will probably yell at you for no key.
You can do
{asciiArray.slice(i * gridWidth, i * gridWidth + gridWidth).map((char, j) => (
<React.Fragment key={j}>{char}</React.Fragment>
))}
if you don’t want a span tag.
As a side note: in the final code block, you can see that {char}, surrounded by curly braces, is nested inside {array.map(...)}. You can nest curly brace interpolation with JSX, but you need to re-enter JSX first. {char} works here because it’s re-wrapped inside a JSX element.
Edit: As the commenter pointed out, you can also remove the map entirely if you only want to output text, because React can automatically render arrays of primitive values.
{asciiArray.slice(i * gridWidth, i * gridWidth + gridWidth)}