I\'m a React noob and making a ToDo list style Recipe List app. I have a functional component, Item.js, and I am using JSX and the map function to iterate through each recipe it
Here is the working version.
class App extends React.Component {
state = {
items: [ "Pumpkin Pie", "Spaghetti", "Onion Pie" ],
ingredients: [
[ "Pumpkin Puree", "Sweetened Condensed Milk", "Eggs", "Pumpkin Pie Spice", "Pie Crust" ],
[ "Noodles", "Tomatoe", "Sauce", "Meatballs" ],
[ "Onion", "Pie Crust" ],
],
}
render() {
return (
<div className="box">
<Item items={this.state.items} ingredients={this.state.ingredients} />
</div>
);
}
}
const Item = props => (
<div>
<div className="Recipe-Item-Container" key={props.text}>
{props.items.map( ( item, index ) => (
<div className="Recipe-Item" key={item}>
<h3>{item}</h3>
<ul>
{
props.ingredients[ index ].map( ingredient =>
<li key={ingredient}>{ingredient}</li> )
}
</ul>
<div className="buttons-container">
<button className="edit-button" onClick={() => props.edit( item, index )}>Edit</button>
<button className="delete-button" onClick={() => props.delete( item, index )}>Delete</button>
</div>
</div>
) )}
</div>
</div>
);
ReactDOM.render(<App />, document.getElementById("root"));
<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="root"></div>
But if I were you I would change my state shape. Something like that:
class App extends React.Component {
state = {
items: [
{
name: "Pumpkin Pie",
ingredients: [
"Pumpkin Puree",
"Sweetened Condensed Milk",
"Eggs",
"Pumpkin Pie Spice",
"Pie Crust"
]
},
{
name: "Spaghetti",
ingredients: ["Noodles", "Tomatoe", "Sauce", "Meatballs"]
},
{
name: "Onion Pie",
ingredients: ["Onion", "Pie Crust"]
}
]
};
removeItem = item => {
const newItems = this.state.items.filter(el => el.name !== item.name);
this.setState({ items: newItems });
};
editItem = item => alert(`${item.name} will be edited`);
renderItems = () =>
this.state.items.map(item => (
<Item
key={item.name}
item={item}
removeItem={this.removeItem}
editItem={this.editItem}
/>
));
render() {
return <div className="box">{this.renderItems()}</div>;
}
}
const Item = props => {
const { item, removeItem, editItem } = props;
const handleRemove = () => removeItem(item);
const handleEdit = () => editItem(item);
return (
<div>
<div className="Recipe-Item-Container" key={props.text}>
<div className="Recipe-Item">
<h3>{item.name}</h3>
<ul>
{item.ingredients.map(ingredient => (
<li key={ingredient}>{ingredient}</li>
))}
</ul>
<div className="buttons-container">
<button className="edit-button" onClick={handleEdit}>
Edit
</button>
<button className="delete-button" onClick={handleRemove}>
Delete
</button>
</div>
</div>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<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="root"></div>
Changes
name
and ingredients
property. Maybe in the future, it may have a unique id
? Objects are flexible.Item
component, we are mapping the items in the parent component and pass just one item to the Item
component.item
prop itself! You can see how we handle the remove functionality: with .filter
You can apply the same functionality to other functions. .map
, .filter
, Object.assign
or spread syntax are all good tools. Just, avoid mutating your state directly.If you add curly braces after the fat arrow, you will have to explicitly return the JSX
.
const Item = (props) => (
<div>
<div className="Recipe-Item-Container" key={props.text}>
{props.items.map((item, index) => {
return (
<div className="Recipe-Item" key={index}>
<h3>{item}</h3>
<p className="ingredients-list">
{props.ingredients[index].map((ingredient, ingredientIndex) => {
return (
<div className="ingredient" key={ingredient}>
{ingredient}
</div>
)
}}
</p>
<div className="buttons-container">
<Button className="edit-button" onClick={() => props.edit(item, index)}>Edit</Button>
<Button className="delete-button" onClick={() => props.delete(item, index)}>Delete</Button>
</div>
</div>
)
}
)}
</div>
</div>
)