Looping through List components in React

Looping through List components in React

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article
This article is sponsored by Fiverr - Freelance to get extra income or become a full-time freelancer.

In the previous article, we saw how to output content dynamically. There's one issue we need to tackle though. That is manually extracting the person's array (persons = [ ... ]) from the state object (const state = { ... }) to each component as attributes (<Person ... />) by zero indexing.

Person's array in the state object:

App.js

const [state, setState] = useState({
    persons: [
      { name: 'Bello', language: 'React', id: '2sdr3' },
      { name: 'Michael', language: 'Vue', id: 'de6c3' },
      { name: 'Mary', language: 'Angular', id: 'c1z3x' }
    ],
    showPersons: true
 });
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
<div>
    <Person
        name={state.persons[0].name}
        language={state.persons[0].language}
        id={state.persons[0].id} />
    <Person
        name={state.persons[1].name}
        language={state.persons[1].language}
        id={state.persons[1].id} />
    <Person
        name={state.persons[2].name}
        language={state.persons[2].language}
        id={state.persons[2].id} />
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

The Zero indexing makes components difficult to maintain, especially for complex apps.

The solution is to use a more elegant approach like ES6+ mapping of arrays.

For example:

JS

const array = [ 1, 4, 5, 2, 7 ];

const arrayFunc = element => {
    return element * 2;
};

array.map(arrayFunc);

// output: [ 2, 8, 10, 4, 14 ]

Array mapping executes each member or element in an array to perform equal operations.

An effective way is to loop through each component in an array by mapping (for-loop or any other approach).

                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
<div>
    {
      state.persons.map(person => {
        return <Person
          name={person.name}
          language={person.language}
          id={person.id} />
      })
    }
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

The overall code:

import React from 'react';
import { useState } from 'react';
import Person from './Person/Person';
import bodyStyles from './body.module.css';

const App = () => {
  const [state, setState] = useState({
    persons: [
      { name: 'Bello', language: 'React', id: '2sdr3' },
      { name: 'Michael', language: 'Vue', id: 'de6c3' },
      { name: 'Mary', language: 'Angular', id: 'c1z3x' }
    ],
    showPersons: true
  });

  const personsToggleHandler = () => {
    const showCards = state.showPersons;
    setState((prevState) => ({
      ...prevState,
      showPersons: !showCards
    }))
  }

  let personsList = state.showPersons ?
    (
      <div>
        {
          state.persons.map(person => {
            return <Person
              name={person.name}
              language={person.language}
              id={person.id} />
          })
        }
      </div>
    ) : null;

  return (
    <div className={bodyStyles.body}>
      <div className='Person-Container'>
        {personsList}
        <h3
          style={{
            textAlign: 'center',
            fontFamily: 'sans-serif'
          }}>Toggle Persons</h3>
      </div>

      <div className={bodyStyles.btns}>
        <button
          className={bodyStyles.button}
          onClick={personsToggleHandler}>Toggle Person Cards</button>
      </div>
    </div>
  );
};

export default App;

Solving the issue above led to a new bug to tackle in the browser console.

Open the browser console with the keyboard shortcut, F12, notice the warning that says, "Warning: Each child in a list should have a unique key prop." That means each person member in the array of the state object must have a key to link to each component list attribute.

The index of each element in a component list must have its key.

App.js

const [state, setState] = useState({
    persons: [
      { name: 'Bello', language: 'React', id: '2sdr3' },
      { name: 'Michael', language: 'Vue', id: 'de6c3' },
      { name: 'Mary', language: 'Angular', id: 'c1z3x' }
    ],
    showPersons: true
 });
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
<div>
    {
      state.persons.map((person, personIndex) => {
        return <Person
          name={person.name}
          language={person.language}
          id={person.id}
          key={personIndex} />
      })
    }
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

Now, there's a new property, personIndex mapping each element in the persons array of the state object to the component list attributes. You will find no error in the console again.

The key is a reserved keyword in JavaScript which acts as an agent to maps each element in the array to component list attributes.

You may wish to omit the personIndex property but use the unique id property for each person's array object to map each component's property.

const [state, setState] = useState({
    persons: [
      { name: 'Bello', language: 'React', id: '2sdr3' },
      { name: 'Michael', language: 'Vue', id: 'de6c3' },
      { name: 'Mary', language: 'Angular', id: 'c1z3x' }
    ],
    showPersons: true
 });
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
<div>
  {
    state.persons.map(person => {
      return <Person
        name={person.name}
        language={person.language}
        id={person.id}
        key={person.id} />
    })
  }
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

Why Use Key?

The key attribute updates the component list effectively because it uses the Virtual DOM to know the specific state that changes. This prevents re-rending the full list whenever a little change is made in a component. That's why we had that warning, informing us to use the key property to manage the state effectively.

In JSX, mapping an array (person's array) to an array function containing the component list is shown below:

JSX

                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
let arrayFunc;
                         ...    ...    ...
<div>
  {
    arrayFunc = (person, personIndex) => {
      return <Person
        name={person.name}
        language={person.language}
        id={person.id}
        key={personIndex} />
    }
  }
  {state.persons.map(arrayFunc)};
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

Although, the arrayFunc function needs to be declared outside of the <div>.

The overall code:

import React from 'react';
import { useState } from 'react';
import Person from './Person/Person';
import bodyStyles from './body.module.css';

const App = () => {
  const [state, setState] = useState({
    persons: [
      { name: 'Bello', language: 'React', id: '2sdr3' },
      { name: 'Michael', language: 'Vue', id: 'de6c3' },
      { name: 'Mary', language: 'Angular', id: 'c1z3x' }
    ],
    showPersons: true
  });

  const personsToggleHandler = () => {
    const showCards = state.showPersons;
    setState((prevState) => ({
      ...prevState,
      showPersons: !showCards
    }))
  }

  let arrayFunc;
  let personsList = state.showPersons ?
    (
      <div>
        {
          arrayFunc = (person, personIndex) => {
            return <Person
              name={person.name}
              language={person.language}
              id={person.id}
              key={personIndex} />
          }
        }
        {state.persons.map(arrayFunc)};
      </div>
    ) : null;

  return (
    <div className={bodyStyles.body}>
      <div className='Person-Container'>
        {personsList}
        <h3
          style={{
            textAlign: 'center',
            fontFamily: 'sans-serif'
          }}>Toggle Persons</h3>
      </div>

      <div className={bodyStyles.btns}>
        <button
          className={bodyStyles.button}
          onClick={personsToggleHandler}>Toggle Person Cards</button>
      </div>
    </div>
  );
};

export default App;

Alternatively, without function declaration, arrayFuncanonymous function:

                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...
<div>
  {
    state.persons.map((person, personIndex) => {
      return <Person
        name={person.name}
        language={person.language}
        id={person.id}
        key={personIndex} />
    };)
  }
</div>
                         ...    ...    ...
                         ...    ...    ...
                         ...    ...    ...

Happy Coding!!!


Buy me a Coffee


Techstack | Fiverr

Techstack article, sponsored by Fiverr.

  • Connect to freelancers with proven business experience.
  • Get matched with the perfect talent by a customer service manager.
  • Freelance to get extra income or become a full-time freelancer.

Sign up to find the perfect freelance services for your business or become a freelancer.

Support what I do and push me to keep making free content.

 
Share this

Impressum

TechStack Media was launched in the year 2020 to make the learning of web technologies easier and more fun.

My name is Bello Osagie, I am the founder of TechStack, and my focus is to give in-depth, senior-level knowledge of the course through a step-by-step approach. You will learn HTML, CSS, JavaScript etc.

You can find my posts on Dev.to, Medium, Hashnode, Hackernoon, and Blogspot

The approach is to first start with the basics, then advance to more topics. Lots of practical examples are added to make learning more easier. TechStack Media also includes videos apart from content writing to make sure you understand all the concepts in a particular topic or course. Contents are frequently updated, so you do not miss out on the latest technology.

If you need a contact me on any of my social media or email:

For exclusive web technology tutorials, join my patron page.

Proudly part of