Can you map() an object array to React?

Asked

Viewed 6,521 times

1

I’m doing a project where I need several recipe cards that will contain: title and ingredients. These cards must be expandable (The user will see the title and when clicking, the ingredients will be shown) and for ease, I am using the Ui Material.

As I do not know the amount (the application will be dynamic), I would like to use map() and I noticed that I will need two map(): One for the cards and one for the list of ingredients that will be rendered inside the card.

Below are: the example of input object I used to test, how I thought to handle this object and the error message displayed.

Input example:

 const teste2 =[{
   title:"Brigadeiro",
   ingredients:["margarina","achocolatado","leite condensado"]
 },{
   title: "Pão assado",
   ingredients:["pão","margarina"]
 }]

Like I thought I would:

 const Recipes = (props) =>{
   let recipesList = props.objects.map((object, index)=>{

     let ingrList = object.ingredients.map((ingred,index)=>(
     <CardText expandable={true}>
       {ingred}
     </CardText>
   ))

     return(
       <Card>
         <CardHeader
           title={object.title}
           actAsExpander={true}
           showExpandableButton={true}
         />
         <CardText>
           {ingrList}
         </CardText>
       </Card>
   )})
 }

Error:

 Recipes(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
 Evaluating index.js

Would anyone have a hint of what to do? Is there any method map() for objects?

Observing:

I tried to separate the objects further, creating one for the ingredient lists and rendering it within the recipe cards, but the property expandable={true} of the component <CardText>crashes (the ingredients are always expanded). It is worth noting that, in this test, I did not use objects.

  • Your code sounds good, where are you using later that Recipes? Where is the main component and the render()?

3 answers

1

The error occurs because there is nothing being returned from the method render(). This is clear from the code and the error message.

Here is my suggestion to solve the problem: divide the user interface into smaller parts. The problem becomes easier to solve. Each component or function should have only one responsibility. Come on:

(1) Create a component Recipes for all recipes.

(2) Create a component Recipe for only one recipe.

(3) Create a component Ingredient for each ingredient.

1. Recipes.js

The Recipes component only cares about showing multiple Recipe components.

(e.g.
  props.recipes === 
    [
      {
        id: 123,
        title: "Brigadeiro",
        ingredients: ["margarina", "achocolatado", "leite condensado"]
      },
      {
        id: 124,
        title: "Pão assado",
        ingredients: ["pão", "margarina"]
      }
    ]
)

const Recipes = (props) => {
  const recipeComponents = props.recipes.map(recipe => (
    <Recipe key={recipe.id} recipe={recipe} />
  ));

  return (
    <div>
      <h1>Receitas</h1>
      {recipeComponents}
    </div>
  );
};

2. Recipe.js

The Recipe component shows an individual recipe (and various ingredients).

(e.g. props.recipe === 
  {
    title:"Brigadeiro",
    ingredients: ["margarina", "achocolatado", "leite condensado"]
  }
)

const Recipe = (props) => {
  const ingredientComponents = props.recipe.ingredients.map(ingredient => (
    <Ingredient key={ingredient} ingredient={ingredient} />
  ));

  return (
    <Card>
      <CardHeader
        title={props.recipe.title}
        actAsExpander={true}
        showExpandableButton={true}
      />
      {ingredientComponents}
   </Card>
  );
};

3. Ingredient.js

The Ingredient component has the role of rendering an individual ingredient.

(e.g. props.ingredient === "margarina")

const Ingredient = (props) => {
  return (
    <CardText expandable={true}>
      {props.ingredient}
    </CardText>
  );
};

Note: all required Mports have been omitted to focus on the issue at hand.

0

I made it with state instead of props, if it works like this just change it later:

import React, { Component } from 'react';

class Recipes extends Component {
    constructor(props) {
        super(props);
        this.state = {
            teste2: [
                {
                    title:"Brigadeiro",
                    ingredients: ["margarina","achocolatado","leite condensado"]
                },{
                    title: "Pão assado",
                    ingredients: ["pão","margarina"]
                }
            ]
        }
    }
    render() {
        return (
            <Card>
                { this.state.teste2.map((valor, x) => {    
                    return (
                        <CardHeader
                            title={ valor.title }
                            actAsExpander={ true }
                            showExpandableButton={ true }
                            key={ x }
                        />
                        <CardText>
                            { valor.ingredients.map((ingred) => {
                                return { ingred }
                            }) }
                            { ingrList }
                        </CardText>                        
                    )                
                }) }
            </Card>
        );
    }
}

-1

const teste2 = [
    {
        title: "Brigadeiro",
        ingredients: ["margarina", "achocolatado", "leite condensado"]
    },
    {
        title: "Pão assado",
        ingredients: ["pão", "margarina"]
    }
]

const Recipes = (props) => {
    const { objects } = props

    const CardContent = objects.map(
        (elem) => {
            <CardHeader
                title={elem.title}
                actAsExpander={true}
                showExpandableButton={true}
            />
            for (ingred of elem.ingredients) {
                <CardText expandable={true}>
                    ingred
                </CardText>
            }
        })
    return (
        <Card>
            <CardContent/>
        </Card>
    )
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.