0

I want to iterate trough an array of objects and display an item in a component, where the prop is the index number of the array item.

This is my code:

import React from 'react';
import './projecten.scss';
import Layout from './../Layout/Layout';
import { ProjectenLijst } from '../../../data';

const Projecten = () => {
  const ProjectItem = ({i}) => (
    <div>{ProjectenLijst[i]}</div>
  )

  return (
    <Layout>
      <ProjectItem i={2}/> // here I want to set the index number of the array
    </Layout>
  )
}

export default Projecten;

And this is the data file I'm pulling the data from:

export const ProjectenLijst = [
  {
    naam: 'Project 1',
    id: 1,
    wat: 'website',
    url: 'https://www.project1.com',
    platform: 'WordPress',
    omschrijving: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis blandit magna leo, sit amet bibendum risus tincidunt non. Duis vitae ligula vel felis tincidunt facilisis. Maecenas interdum ligula ut vestibulum scelerisque. Aenean vestibulum ultrices augue. Mauris nec aliquam nulla, quis ultrices arcu. Aliquam fringilla.',
    img: ''
  },

  {
    naam: 'Project 2',
    id: 2,
    wat: 'website',
    url: 'https://www.project2.com',
    platform: 'WordPress',
    omschrijving: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis blandit magna leo, sit amet bibendum risus tincidunt non. Duis vitae ligula vel felis tincidunt facilisis. Maecenas interdum ligula ut vestibulum scelerisque. Aenean vestibulum ultrices augue. Mauris nec aliquam nulla, quis ultrices arcu. Aliquam fringilla.',
    img: ''
  },

  {
    naam: 'Project 3',
    id: 3,
    wat: 'website',
    url: 'https://www.project3.com',
    platform: 'WordPress',
    omschrijving: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis blandit magna leo, sit amet bibendum risus tincidunt non. Duis vitae ligula vel felis tincidunt facilisis. Maecenas interdum ligula ut vestibulum scelerisque. Aenean vestibulum ultrices augue. Mauris nec aliquam nulla, quis ultrices arcu. Aliquam fringilla.',
    img: 'https://images.pexels.com/photos/4873818/pexels-photo-4873818.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'
  }
];

I can't get this to work. The code renders the page, but the part where the project item should render stays empty. I'm overlooking something..but what am I doing wrong? :-)

Thanks!

//Ninja-edit: cleaned the code some more

8
  • Remove the wiggly brackets where you index into the array. One set around the entire expression is enough. You’re not indexing with a number, but instead an object that has a key/value of i. Commented Sep 18, 2020 at 11:54
  • Then I get the error: Error: Objects are not valid as a React child (found: object with keys {naam, id, wat, url, platform, omschrijving, img}). If you meant to render a collection of children, use an array instead. Commented Sep 18, 2020 at 11:57
  • The code drastically changed since my comment. You may find a solution to your problem, but i think it's easy to miss the explanation. There seem to be several problems that are shifted around. Commented Sep 18, 2020 at 19:40
  • The code didn't drastically changed. I only removed the curly braces from the first (i) call. Commented Sep 19, 2020 at 20:25
  • That's quite a drastic change. The first part of the accepted answer no longer seems relevant. Commented Sep 20, 2020 at 0:30

3 Answers 3

1

There are two problems.

  1. When you call ProjectenLijst using <ProjectItem i={2} /> you must extract the i property by using curly braces:

    const ProjectItem = (i) => (/* ... */);
    // should be
    const ProjectItem = ({i}) => (/* ... */);
    

    See Destructuring assignment - Object destructuring

  2. You can't render complex objects, only scalar values. Meaning that:

    <div>{ProjectenLijst[i]}</div>
    // should for example be
    <div>{ProjectenLijst[i].naam}</div>
    

// mock
const Layout = (props) => <div {...props} />;
const ProjectenLijst = [
  { naam: 'Project 1', id: 1 },
  { naam: 'Project 2', id: 2 },
  { naam: 'Project 3', id: 3 },
];

// answer
const Projecten = () => {
  const ProjectItem = ({i}) => (        // extract the "i" property by using curly braces
    <div>{ProjectenLijst[i].naam}</div> // refer to a scalar property, not the whole object
  );

  return (
    <Layout>
      <ProjectItem i={2} />
    </Layout>
  );
};

ReactDOM.render(<Projecten />, document.querySelector("#root"));
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>

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

Comments

0
import React from 'react';
import './projecten.scss';
import Layout from './../Layout/Layout';
import { ProjectenLijst } from '../../../data';

const Projecten = () => {
  const ProjectItem = (i) => (
    <div>{ProjectenLijst[i].name}</div>
  )

  return (
    <Layout>
      {ProjectenLijst.map((item, index) => {
         return <ProjectItem i={index}/>
      })}
    </Layout>
  )
}

export default Projecten;

or

import React from 'react';
import './projecten.scss';
import Layout from './../Layout/Layout';
import { ProjectenLijst } from '../../../data';

const Projecten = () => {
  const ProjectItem = (item) => (
    <div>{item.name}</div>
  )

  return (
    <Layout>
      {ProjectenLijst.map(item => {
         return <ProjectItem item={item}/>
      })}
    </Layout>
  )
}

4 Comments

Thanks for your comment. I also tried your methods, but that doesn't work either. I don't understand what the issue is here :-)
@Paul sorry, I've misspelled name. It is naam in your objects
It's not that, the issue with this answer is that you don't pass props properly. It should be item.item.naam if you want this to work.
Or ProjectItem = ({item})=>...
0

To elaborate on the initial comment, since the code changed:

const ProjectItem = ({i}) => (
  <div>{ProjectenLijst[{i}]}</div>
)

First, you made a functional component, hence you can call:

<ProjectItem i={0} foo="foo" bar="bar">

Let's rewrite the the functional component to not destructure the arguments:

const ProjectItem = (props)=> {
  console.log(props.i) //0
  console.log(props.foo) //"foo"
  console.log(props.bar) //"bar"
  ...
}

Since we only need the i prop/key, we can destructure this, both the argument:

const ProjectItem = ({i})=>{...}

Or inside the function, say if we wanted to pass the whole props object to another component:

const ProjectItem = (props)=>{
  const {i,foo} = props //to use locally
  const aThing = thingMaker(props)
  ...
}

Let's remind ourselves how we index into an array:

const i = 0
const someObject = { i: i }
const alternatively = { i } //shorthand to {i:i}

const someArray = [0,1,2,3]

console.log(someArray[ i ]) //0 first element
console.log(someArray[ someObject ]) //i think it will be undefined, 

Simply you can't index with an object into the array.

Applying all of this into your original snippet, and removing most of the shorthands

const ProjectItem = (props)=>{
  // get the index
  const { i } = props          //destructure
  const { i: myIndex } = props //destructure and alias
  const _i = props.i           //same thing no destructuring

  // get the item (use any of these)
  const myItem0 = ProjectenLijst[i]
  const myItem1 = ProjectenLijst[props.i]
  const myItem2 = ProjectenLijst[myIndex]
  const myItem3 = ProjectenLijst[_i]

  //JSX

  return <div> 
   { myItem0 } 
  </div> 
 
}

Notice the { myItem0 } you have one set of braces {} and a variable in between.

So to recap, what you were doing with:

const ProjectItem = ({i}) => (
  <div>{ProjectenLijst[{i}]}</div>
)

is:

const ProjectItem = (props)=> {
  const someArbitraryObject = { i: props.i }
  const item = ProjectenLijst[ someArbitraryObject ]

  console.log(someArbitraryObject) // { i: 0 }
  console.log(item) // undefined

  return <div>{item}</div>
}

This was just one of the issues with the original code - indexing into arrays and destructuring. Other answers about what can be rendered with JSX etc. also apply.

1 Comment

Thanks! This really helps understanding the structures <3

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.