javascript - applying map function works while foreach function doesnt reactjs
问题描述
I have a react app which show items from a nested json using map function, however one of the categories can be empty which crashes the whole application, I have tested the foreach function for the same json using js's for each function and it worked perfectly, I am trying to translate the same logic which would solve the empty category issue.
here is my for each test on the same json but with lists:
Test1
let obj = {
"name": "Menu",
"children": [
{
"type": "category",
"name": "Burgers",
"children": [
{
"type": "item",
"name": "Burger 1",
"children": [
{
"type": "modifier",
"name": "Promo",
"children": [
{
"type": "item",
"name": "Promo 1"
}
]
},
{
"type": "group",
"name": "Drinks",
"children": [
{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [
{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Tomato"
},
{
"type": "ingredient",
"name": "Pickles"
}
]
}
]
},
{
"type": "item",
"name": "Burger 2",
"children": [
{
"type": "modifier",
"name": "Promo",
"children": [
{
"type": "item",
"name": "Promo 1"
}
]
},
{
"type": "group",
"name": "Drinks",
"children": [
{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [
{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Tomato"
},
{
"type": "ingredient",
"name": "Pickles"
}
]
}
]
},
{
"type": "item",
"name": "Coming Soon Offers"
}
]
},
{
"type": "category",
"name": "Pizzas",
"children": [
{
"type": "item",
"name": "Pizza 1",
"children": [
{
"type": "modifier",
"name": "Promo",
"children": [
{
"type": "item",
"name": "Promo 1"
}
]
},
{
"type": "group",
"name": "Drinks",
"children": [
{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [
{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Mashrooms"
},
{
"type": "ingredient",
"name": "Olives"
}
]
}
]
},
{
"type": "item",
"name": "Pizza 2",
"children": [
{
"type": "modifier",
"name": "Promo",
"children": [
{
"type": "item",
"name": "Promo 1"
}
]
},
{
"type": "group",
"name": "Drinks",
"children": [
{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [
{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Mashrooms"
},
{
"type": "ingredient",
"name": "Olives"
}
]
}
]
}
]
}
]
}
let body = document.querySelector('body');
function print(obj){
let str = `<li>${obj.name}</li>`;
if(obj.children){
str += '<ul>'
for(let c of obj.children) str += print(c)
str += '</ul>'
}
return str;
}
document.body.innerHTML = print(obj);
Test 2
const buildMenu = (data) => {
let ul = document.createElement('ul');
data.children.forEach(i => {
let li = document.createElement('li');
li.innerText = i.name;
li.className = i.type;
if (i.children) li.appendChild(buildMenu(i));
ul.appendChild(li);
});
return ul;
};
let data = {
"name": "Menu",
"children": [{
"type": "category",
"name": "Burgers",
"children": [{
"type": "item",
"name": "Burger 1",
"children": [{
"type": "modifier",
"name": "Promo",
"children": [{
"type": "item",
"name": "Promo 1"
}]
},
{
"type": "group",
"name": "Drinks",
"children": [{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Tomato"
},
{
"type": "ingredient",
"name": "Pickles"
}
]
}
]
},
{
"type": "item",
"name": "Burger 2",
"children": [{
"type": "modifier",
"name": "Promo",
"children": [{
"type": "item",
"name": "Promo 1"
}]
},
{
"type": "group",
"name": "Drinks",
"children": [{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Tomato"
},
{
"type": "ingredient",
"name": "Pickles"
}
]
}
]
},
{
"type": "item",
"name": "Coming Soon Offers"
}
]
},
{
"type": "category",
"name": "Pizzas",
"children": [{
"type": "item",
"name": "Pizza 1",
"children": [{
"type": "modifier",
"name": "Promo",
"children": [{
"type": "item",
"name": "Promo 1"
}]
},
{
"type": "group",
"name": "Drinks",
"children": [{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Mashrooms"
},
{
"type": "ingredient",
"name": "Olives"
}
]
}
]
},
{
"type": "item",
"name": "Pizza 2",
"children": [{
"type": "modifier",
"name": "Promo",
"children": [{
"type": "item",
"name": "Promo 1"
}]
},
{
"type": "group",
"name": "Drinks",
"children": [{
"type": "item",
"name": "Coke"
},
{
"type": "item",
"name": "Light Coke"
},
{
"type": "item",
"name": "Sprite"
},
{
"type": "item",
"name": "Fanta"
}
]
},
{
"type": "modifier",
"name": "Without",
"children": [{
"type": "ingredient",
"name": "Onion"
},
{
"type": "ingredient",
"name": "Mashrooms"
},
{
"type": "ingredient",
"name": "Olives"
}
]
}
]
}
]
}
]
};
document.body.appendChild(buildMenu(data));
解决方案
您在多个地方缺少对象空检查。
- 在
ItemList
组件的渲染函数中有一个 else 语句,您可以在其中分配 selectedChild 和 selectedItem。您需要检查activelist.children
andselectedChild.children
是否为空
const selectedChild = activelist.children.length ? activelist.children[this.state.selected] : null;
const selectedItem = selectedChild.children && selectedChild.children.length
? selectedChild.children[this.state.itemSelected]: null;
- 要渲染 selectedChild,您应该检查 children 是否为空。
{
selectedChild &&
selectedChild.children &&
selectedChild.children.length &&
selectedChild.children.map(
(item, index) => (
<Item
className="person"
key={index}
Title={item.name}
onClick={this.handleClick}
index={index}
/>
)
)}
- 要呈现 selectedItem,您应该检查 children 是否为空
<div>
{ selectedItem &&
selectedItem.children &&
selectedItem.children.map((item, index) => (
<Modifiers
key={index}
title={item.name}
myKey={index}
options={item.children}
childk={item.id}
/>
))
}
</div>
<div>
{
selectedItem &&
selectedItem.size &&
(<div>
<Size
options={selectedItem.size}
sizetitle={"Size"}
/>
</div>)
}
</div>
推荐阅读
- python - 使用 pandas,如何对包含字符串元素列表中的字符串元素的所有值的表进行排序?
- python - 尝试使用 python gui 使用 Telethon 提取数据时出现错误
- javascript - 将数组导出到 Node.js 中的另一个文件
- authentication - 我无法登录 snowsql 命令提示符
- reactjs - 带有 useState 的 localStorage 的奇怪错误反应
- rust - Rust 错误未能解析清单未指定目标
- c++ - 堆栈为空时抛出异常的问题.....队列/堆栈实现
- python - 提取括号和嵌套括号之间的字符串
- ios - 在 swiftui 中构建用户模型
- html - 用于响应式卡片图像和内容的 Flexbox - 博客