我是一名学生,是新来的人。我正在创建一个思维树,其中的组件呈现出数组之外,最终将拥有自己的子级。我遇到了一个问题,其中呈现了(第一个孩子的)另一个重复孩子。它只会在三点之后发生,并且永远不会成为数据结构本身的一部分。我找不到发布的许多类似问题,如果您有任何想法,将不胜感激!
displayChildren = () => {
let num = 1;
let childs = [];
if(this.props.Data.Children == null)
return;
this.props.Data.Children.map(idea => {
childs.push(
<td key = {'R-'+this.props.Data.Children.length}>
<Idea key={'I-'+this.props.Data.Children.length} Data={idea} pushToTop={this.pushToTop}/>
</td>
);
console.log("Creating Child >"+ num++ +"< for "+this.props.Data.Title, childs);
});
console.log("FINISHED CHILDREN: ", childs);
return(<tr align="center" valign="top">{childs}</tr>);
}Picture: Two Children -> Working
图片:两个孩子的日志->数据中有两个孩子。
图片:三个孩子->错误,重复渲染->显示四个孩子
注意:连接基于数组的大小(三个),因此仅显示三个。
图片:三个孩子的日志->数据中的三个孩子
其他说明:我最终希望拥有多个用户,并计划使用Socket.IO通过替换树的头/原点来回传递当前数据。借助Socket,它可以将额外的组件呈现给用户,从而使浏览器立即崩溃。
答案 0 :(得分:1)
您的代码还有很大的改进空间。我将从重做它开始,然后解释一些更改背后的原因。
displayChildren = () => {
if (!Array.isArray(this.props.Data.Children)) return;
const childs = this.props.Data.Children.map((idea, i) => {
console.log(`Creating Child >${i}< for ${this.props.Data.Title}`, this.props.Data.Children);
return (
<td key = {`R-${idea.Title}`}>
<Idea Data={idea} pushToTop={this.pushToTop}/>
</td>
);
});
console.log("FINISHED CHILDREN: ", childs);
return(<tr align="center" valign="top">{childs}</tr>);
}
如果上述代码解决了问题,则主要的问题是您为所有<td>
使用了相同的密钥,因为this.props.Data.Children.length
将始终相同-它不会随您的变化而变化map
遍历数组中的每个元素。
相反,我使用idea.Title
为每个<td>
构建(希望)唯一的密钥。您还可以使用i
(index
的缩写,map
提供给回调函数的第二个参数,我也在内部console.log
语句中使用了该参数),但是在某些情况下可能会出现问题(例如,如果要动态地添加,删除或对this.props.Data.Children
数组中的元素进行排序)。
其他改进:
不要创建数组,然后在push
内map
到它。无论如何,在数组上进行映射都会返回一个新数组,因此无需推送到单独的数组。
Prefer string literal syntax to string concatenation with the +
symbol.
Idea
在这里不需要唯一键。只有<td>
个。
我没有在尝试this.props.Data.Children
之前检查null
是否等于map
,而是检查它是否为数组。如果您不小心将this.props.Data.Children
设置为null
或数组之外的其他内容,这样做会更安全。
还有更多改进的空间,但这超出了此答案的范围。
答案 1 :(得分:0)
key
必须是唯一的,而在您的代码中则并非如此。非唯一键可能导致像您一样的奇怪行为。请为循环中的每个<td>
生成一个唯一的密钥,它将解决您的问题。
<td key = {'R-'+this.props.Data.Children.length}>