2

Imagine I have an array of objects like so:

const chefs = [
  {
    key: 1,
    images: ['http://lorempixel.com/400/400/sports/', 'http://lorempixel.com/400/400/abstract/', 'http://lorempixel.com/400/400/animals/', 'http://lorempixel.com/400/400/city/', 'http://lorempixel.com/400/400/people/']
  }
]

And I'm wanting to assign each of the images inside of the images array to a React component called CarrouselItem using props:

class CarrouselItem extends React.Component {
  render() {

    return (
      <div>
        <img src={this.props.imageUrl} />
      </div>
    )
  }
}

Which is then placed into a parent component called Carrousel, where I loop over the object and return the images inside, to be placed inside of the CarrouselItem component:

class Carrousel extends React.Component {
  render() {
    return (
      <div>
        <h4>Slide image</h4>
        {chefs.map((chef, index) => {
          return <CarrouselItem imageUrl={chef.images[index]} />
        })}
      </div>
    )
  }
}

What I expect to happen

The map function should iterate over all of the objects (in this case, just one of them) which then creates X number of CarrouselItem components, each with an <img> that's taken from the images array.

What actually happens

Unfortunately I'm only getting the first item in the array (in this case, 'http://lorempixel.com/400/400/sports/').

Could someone be so kind to explain where I'm going wrong here?

Link to CodePen.

3 Answers 3

6

First you need to iterate over chefs array, and then individual images.

const chefs = [
  {
    key: 1,
    images: ['http://lorempixel.com/400/400/sports/', 'http://lorempixel.com/400/400/abstract/', 'http://lorempixel.com/400/400/animals/', 'http://lorempixel.com/400/400/city/', 'http://lorempixel.com/400/400/people/']
  }
]

class Carrousel extends React.Component {
  render() {
    return (
      <div>
        <h4>Slide image</h4>
        {chefs.map((chef, i)=>(
          <div key={i}>
            {chef.images.map((image,index)=>(
              <CarrouselItem imageUrl={image} key={index} />
            ))}
          </div>  
        ))}
        ))
      </div>
    )
  }
}

class CarrouselItem extends React.Component {
  render() {

    return (
      <div>
        <img src={this.props.imageUrl} />
      </div>
    )
  }
}

ReactDOM.render(<Carrousel />,document.getElementById("app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks anuragasaurus, I did consider doing this, although I don't know why but it just "feels" like bad practice to me... although it works for now, so thank you! I'll select this as the correct answer (if I can) and then amend it if there's a better solution posted. Thanks again!
@A7DC why do you feel it's a bad practice? Your array of chefs has array of images, so you'll need to iterate twice.
Ok, awesome. I'm not sure, it's just when I thought of doing that it seemed quite verbose, and I figured there would be a more concise way of doing it - but it seems not as two of you came up with a similar solution. So thanks again!
2

The reason why its only giving you one item, is because you are mapping over a chef and not his images.. so you only iterate once. Instead you just want to map over the images like so chefs.images.map

const chefs = [
  {
    key: 1,
    images: ['http://lorempixel.com/400/400/sports/', 'http://lorempixel.com/400/400/abstract/', 'http://lorempixel.com/400/400/animals/', 'http://lorempixel.com/400/400/city/', 'http://lorempixel.com/400/400/people/']
  }
]

class Carrousel extends React.Component {
  render() {
    const elems = [];
    chefs.forEach( (chef) => {
        chef && chef.images.forEach( (image, j) => {
            elems.push(<CarrouselItem imageUrl={image} key={i} />)
        })
    })
    return (
      <div>
        <h4>Slide image</h4>
        {elems}
      </div>
    )
  }
}

I would recommend you make a chef component that renders things like the chefs information, name, age, location, restaurant... etc.. and renders a carousel for each chef with their images.

5 Comments

That was a quick reply, thanks! Although that's what I figured earlier, although whenever I try to map over the chefs.images it returns TypeError: undefined is not an object (evaluating 'chefs.images.map').
@A7DC sounds like you have some invalid data somewhere. I'll handle that in my answer one sec while I edit
@JohnRuddell doesn't he'll need to iterate over chefs array to get indivial chef element.
Thanks mate, you're a legend. I'm not sure which is the better answer (yours or anuragasaurus), so I'll leave his as the "correct" answer for now until other people have reviewed both the comments. But thanks again man! I really appreciate it 🙌
@A7DC no worries :) I personally like my answer as to me its more readable, but both are perfectly acceptable answers :) I also added a recommendation of what I would do to lay out the data better :)
1

actually its picking chef object index which is one so you getting first instead use chefs.images.map

{chefs[0].images.map((image, index) => {
          return <CarrouselItem imageUrl={image} />
        })}

3 Comments

As with the above comment: whenever I try to map over the chefs.images it returns TypeError: undefined is not an object (evaluating 'chefs.images.map'). Not sure why this is? Thanks for the reply by the way!
you can use subindex chefs[0]
You're right, but unfortunately this would break if more than one chef was added to the chefs array, right?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.