ohadinho ohadinho - 2 months ago 13
Javascript Question

Syntax Error - Map multidimensional array in React-Redux

I've been scratching my head for hours trying to figure out why do I get a syntax error when trying to iterate a multidimensional array :

const InputPanel = React.createClass({
render() {
const { board } = this.props;

return(
<br />
{board.map(rows => {
rows.map(cell => <div className="digit">1</div>);
})
}
);

}
});


CodePen:

http://codepen.io/anon/pen/vXgmrR

I tried to add\modify parenthesis types and nothing helps.

Here is the view i'm trying to produce:

</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>
</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>
</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>

Answer

There are a couple of problems with the code.

  1. Your rows.map(...) statement isn't actually outputting anything. You need to return the result of rows.map to have it rendered.

You could do this:

{board.map(rows => {
        return rows.map(cell => <div className="digit">1</div>); 
    })
}

or this:

{board.map(rows => rows.map(cell => <div className="digit">1</div>))}
  1. It's not clear to me if this in the render method will actually reference the component. I usually use ES2015 classes or stateless functions to create my components, simply because the logic seems clearer to me.

So, your component could be rewritten:

class InputPanel extends React.Component {
    render() {
        const { board } = this.props;

        return(
            <br />
            {board.map(rows =>
                    rows.map(cell => <div className="digit">1</div>)
                )
            }
        );

    }
}

or, even more simply:

const InputPanel = ({ board }) =>  (
    <br />
    {board.map(rows => rows.map(cell => <div className="digit">1</div>))}
);

Now, I could be wrong about this - like I said, I'm not that familiar with the React.createClass way of doing things.

  1. React is not going to like that bare <br /> in your component. render methods need to return a single element, so you're going to need to wrap everything in your render method in a <div> or some other element.

And this final one is the source of your syntax error: without that wrapping element, Javascript (or more accurately whatever system you're using to interpret JSX code) sees something like this:

return (
    { /* some Javascript code here */ }
);

which is not valid Javascript - you can't just return a code block like that.

With an enclosing <div>, the code looks like this:

return (
    <div>
        { /* some Javascript code here */ }
    </div>
);

which is valid JSX code and your JSX preprocessor can parse it.

So, to wrap it all up, the simplest form of your component would look something like this:

const InputPanel = ({ board }) =>  (
    <div>
        {board.map(rows => rows.map(cell => <div className="digit">1</div>))}
    </div>
);

As an aside, I'd recommend looking into eslint to lint your code & catch errors like this. I try to use it religiously and I like to think it has improved my code quality :-)