Reputation: 11
I'm trying to make a dynamic burger builder in ReactJS. As soon as the homepage opens, I get an error like this:
TypeError: Cannot read property 'name' of undefined
IngredientsMenuItem
/src/components/IngredientsMenu/IngredientsMenuItem.js:18
15 | return (
16 | <ItemWrapper>
17 | <ItemContent>
> 18 | <h3>{item.ingredient.name}</h3>
| ^ 19 | <h4>{item.ingredient.price}</h4>
20 | <Counter
21 | value={item.qty}
I keep my burger in a context.
My ingredients file:
export const ingredients= [
{
name:"salad",
price:0.5,
},
{
name:"cheese",
price:0.4,
},
{
name:"meat",
price:1.3,
},
];
My home page:
const Home = () => {
const {burger,updateBurger} = useContext(BurgerContext);
return (
<div>
{!burger.length && updateBurger(buildBurger(ingredients))}
<Burger/>
<IngredientsMenu
ingredients={ingredients}
/>
</div>
)
}
export default Home
My buildBurger function:
export const buildBurger = (ingredients) => {
return [
ingredients.map((ingredient) => (
{
qty:0,
ingredient: ingredient
}
))
]
}
I did this to create a template for ingredients with values 0 in the initial state.
My IngredientsMenu:
const IngredientsMenu = ({ingredients}) => {
const {burger, updateBurger} = useContext(BurgerContext);
return (
<>
<Wrapper>
{burger.map((item) => (
<IngredientsMenuItem
item={item}
/>
))}
</Wrapper>
</>
)
}
export default IngredientsMenu
My IngredientsMenuItem:
const IngredientsMenuItem = ({item) => {
const {burger, updateBurger} = useContext(BurgerContext);
const handleIncrement = (burgerItem) => {
}
const handleDecrement = (burgerItem) => {
}
return (
<ItemWrapper>
<ItemContent>
<h3>{item.ingredient.name}</h3>
<h4>{item.ingredient.price}</h4>
<Counter
value={item.qty}
onIncrement={() => handleIncrement(item)}
onDecrement={() => handleDecrement(item)}
/>
</ItemContent>
</ItemWrapper>
)
}
export default IngredientsMenuItem
I couldn't see where my fault was. Is there anyone who can help?
Upvotes: 0
Views: 119
Reputation: 4942
On your component IngredientsMenuItem
, the item
prop is probably null
or undefined
.
Consider adding a console.log
instruction inside your component to see what's exactly there.
If you want your code to "never break", you can check if the contents are there, and if they are not, revert to an empty object, like so:
const IngredientsMenuItem = ({item) => {
const {burger, updateBurger} = useContext(BurgerContext);
const handleIncrement = (burgerItem) => {
}
const handleDecrement = (burgerItem) => {
}
const ingredient = (item && item.ingredient) || {};
// this can be replaced to a shorter version if you support the `?.` operator:
// const ingredient = item?.ingredient || {};
const qty = (item && item.qty) || 0;
return (
<ItemWrapper>
<ItemContent>
<h3>{ingredient.name}</h3>
<h4>{ingredient.price}</h4>
<Counter
value={qty}
onIncrement={() => handleIncrement(item)}
onDecrement={() => handleDecrement(item)}
/>
</ItemContent>
</ItemWrapper>
)
}
Upvotes: 1