kibowki
kibowki

Reputation: 4376

How to loop through object in JSX using React.js

So I have a React.js component, and I want to loop through an object I import to add HTML options to it. Here is what I tried, which is both ugly and does not work:

import React from 'react';
import AccountTypes from '../data/AccountType';

const AccountTypeSelect = (props) => {  
  return (
    <select id={props.id} className = {props.classString} style={props.styleObject}>
        <option value="nothingSelected" defaultValue>--Select--</option>
        {
            $.each(AccountTypes, function(index) {
                <option val={this.id}>this.name</option>
            })
        }
    </select>
  );
};

export default AccountTypeSelect;

I received this error in the console from the above code:

invariant.js?4599:38 - Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {id, name, enabled, additionalInfo}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of AccountTypeSelect.

Do I really need to convert each object into an array or wrap it with createFragment to use it? What is the best practice for this case?

Upvotes: 20

Views: 36186

Answers (4)

Points to note :

Your data is in an Object , not in an array : therefore to loop through it , you will have to use Object.keys(yourObject).map() instead of yourObject.map()

With this in mind ; here is the solution

var user = {
     fname:'John',
     lname : 'Doe',
     email:'[email protected]'
}

class App extends Component {
  render() {
    return (
      <p>
      <ul>
        {
          Object.keys(user).map((oneKey,i)=>{
            return (
                <li key={i}>{user[oneKey]}</li>
              )
          })
        }

      </ul>    
      </p>
    );
  }
}

If you're using TypeScript:

(Object.keys(user) as (keyof typeof user)[]).map((oneKey,i)=>{
    return (
       <li key={i}>{user[oneKey]}</li>
    )
})

Upvotes: 54

Kevin
Kevin

Reputation: 25269

Instead of $.each use map:

{AccountTypes.map(function(a) {
     return (
         <option key={a.id} val={a.id}>{a.name}</option>
     );
 })}

Upvotes: 10

Phi Nguyen
Phi Nguyen

Reputation: 3056

for rendering a list of children, you must add key attribute for each child so React will render them properly.Try this:

With JQuery map ( good for functional programming)

   {
        $.map(AccountTypes, function(type,index) {
            return <option key={type.id} val={type.id}>type.name</option>
        })
    }

With normal map :

{AccountTypes.map((type) => {
   return <option key={type.id} 
                  val={type.id}>
            {type.name}
          </option>
)}

Upvotes: 0

Matteo Frana
Matteo Frana

Reputation: 579

You should use map to loop:

{AccountTypes.map((accountType) => 
  <option value={accountType.id}>{accountType.name}</option>)}

Upvotes: 0

Related Questions