0

I am new to react (I am incorporating it into my ruby on rails project), here the component ive made:

  <div id="articles"></div>
  <script type="text/jsx">



var Article=React.createClass({
    render: function(){
         return(
           <div>
             {this.props.data}.map(function(item){
               {item.name}  
             })
           </div>
         )
    }
});




var input = [{name: "hello", email: "[email protected]"}]

React.render(<Article data={input} />, document.getElementById("articles"))

When i run this, this is the error i get:

Uncaught Error: Parse Error: Line 7: Unexpected token .

{item.name}  

I have set a prop to be an array. I just want to output the name hash key inside the array - why am i getting this error, it seems to me that this should work ?

2 Answers 2

3

You're not returning anything inside your map-statement, try writing

return {item.name};

However, I would suggest you try moving your map-function outside of the immediate render, its easier to read and less error-prone.

 <div id="articles"></div>
  <script type="text/jsx">

var Article=React.createClass({
    render: function() {
         var rows = this.props.data.map(function(item) {
               //You could return any valid jsx here, like <span>{item.name}</span>
               return item.name;
         });
         return(
           <div>  
               {rows}
           </div>
         )
    }
});

var input = [{name: "hello", email: "[email protected]"}
React.render(<Article data={input} />, document.getElementById("articles"))
Sign up to request clarification or add additional context in comments.

Comments

2

In JSX you have two 'modes'. JS mode (default) and JSX mode.

You enter JSX mode with a tag, like <div. In JSX mode only tags, attributes, and arbitrary text are allowed. You are also allowed to go into a JS mode with {}. This can happen any number of times.

function jsMode(){
    <jsx>
        {js(
            moreJs,
            <moreJsx>{evenMoreJs}</moreJsx>
        )}
    </jsx>;
}

So coming back to your code:

<div>
    {this.props.data}.map(function(item){
        {item.name}  
    })
</div>

Let's break this down into chunks

// js mode
<div> // begin jsx
{ // begin js
    this.props.data // some js code
} // end js, back to jsx
.map(function(item) // this is just plain text visible to the user
{ // begin js
{item.name} // some invalid js, SyntaxError
} // end js
) // this is just plain text visible to the user
</div> // end jsx
// js mode

Because you want the .map to be interpreted as JS, and you were previously in JSX mode, it should also be in the {}s.

<div>
    {this.props.data.map(function(item){
        {item.name}  
    })}
</div>

Also, inside the .map callback, you're still in JS mode, so you need to remove the {}s

<div>
    {this.props.data.map(function(item){
        item.name
    })}
</div>

And finally, you need to return the name from the .map callback.

<div>
    {this.props.data.map(function(item){
        return item.name;
    })}
</div>

Other stuff

The code above will work, but probably not as expected.

If data was [{name: 'foo'}, {name: 'bar'}], map will return ['foo', 'bar'], and react will render it as:

<span>foo</span><span>bar</span>

To the user this appears as "foobar". If you want it to appear as two separate words you could put a space after each name:

<div>
    {this.props.data.map(function(item){
        return item.name + " ";
    })}
</div>

Or return an element from .map and style it as you like. For example, an unordered list of names. Note that here we wrap item.name in {}s because we enter JSX mode.

<ul>
    {this.props.data.map(function(item, i){
        return <li key={i}>{item.name}</li>;
    })}
</ul>

We also provide a key. In this case it's the index of the item, which works as long as the list never changes, or only has items added/removed to/from the end of the array.

picture of stack data structure

Image credit: wikipedia/commons

If the array is reordered, or items are added/remove to/from the start or middle, we need a unique string identifier for each item.

If your data was [{name: "foo", id: "14019751"}, {name: "bar", id: "13409185"}], then:

<ul>
    {this.props.data.map(function(item, i){
        return <li key={item.id}>{item.name}</li>;
    })}
</ul>

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.