Trax
Trax

Reputation: 1538

React nested rendering

I have an object containing several arrays like:

const Items = {
Deserts: [{name:cookies}, {name:chocolate}],
Fruits: [{name:apple}, {name:orange}]
...
}

I want to render it as:

<title>Deserts</title>
Cookies
Chocolate
<title>Fruits</title>
Apple
Orange

So first I render the type:


return <Grid>
    {Object.keys(Items).map(type => {
        return <Box key={type}>
            {type} // <== this would be the title, Fruits or whatever
            {this.createCard(Items[type])}
        </Box>
    })}
</Grid>

Then I want to add the content of each type:

createCard = (items) => {
  return <Box>
       {items.forEach(item => {
           return <div>{item.name}</div>
       })}
  </Box>
}

Content is not returned, it works fine if instead of a forEach loop I just add some predefined content.

Upvotes: 1

Views: 318

Answers (2)

b.stevens.photo
b.stevens.photo

Reputation: 934

When returning an element you need to wrap it in parentheses, ( ) and I generally use map instead of forEach.

const createCard = items => {
   return (
      <Box>
       {items.map(item => {
           return ( <div>{item.name}</div> )
       })}
     </Box>
   )
}

I believe you can also nix the curly braces if the function doesn't need any logic.

const createCard = items => (
    <Box>
        {items.map(item => {
            return ( <div>{item.name}</div> )
        })}
    </Box>
)

-- Edit --

Now that I'm reading back over your question a much cleaner way to approach this would be to declare the component function outside of your class like

class Grid extends react.Component {
   render(){
      return (
         <Box>
            <CreateCard props={ item }/>
         </Box
      )
   }
}

const CreateCard = props => (
    <Box>
        {props.items.map(item => {
            return ( <div>{item.name}</div> )
        })}
    </Box>
)

Upvotes: 0

mgarcia
mgarcia

Reputation: 6325

The forEach method only iterates over all items but does not return anything. Instead, what you want to use is a map. Also, make sure you wrap your return value when it extends more than one line:

createCard = (items) => {
  return (<Box>
       {items.map(item => {
           return <div>{item.name}</div>
       })}
  </Box>);
}

If you don't do that it works as if a semicolon was introduced after the first line. So, in reality, your current code is equivalent to:

createCard = (items) => {
  return <Box>;
  // The code below will never be executed!
       {items.forEach(item => {
           return <div>{item.name}</div>
       })}
  </Box>
}

Upvotes: 2

Related Questions