正如标题所述,使用React.cloneElement
insideReact.Children.map
会导致元素键发生变化。
这是一个沙箱,演示了这一点。
React.Children.map(children, (child) => {
let clonedEl = React.cloneElement( child );
console.log(clonedEl);
return clonedEl;
});
该代码块的结果具有.$
添加到每个键前面的元素。这确实令人困惑,原因有两个。
1:文档说cloneElement将保留键和引用。
使用 element 作为起点克隆并返回一个新的 React 元素。生成的元素将具有原始元素的 props,新的 props 浅合并。新的孩子将取代现有的孩子。原始元素的 key 和 ref 将被保留。
2:结果console.log
是一个带有保留键和引用的元素...
这会让我相信添加是在 React.Children.map 代码中的某个地方发生的。
更新:查看 React.Children.map 的代码后...
我发现它是通过以下函数链添加的:mapChilren -> mapIntoWithKeyPrefixInternal -> traverseAllChildren -> traverseAllChildrenImpl -> mapSingleChildIntoContext。
mapSingleChildIntoContext
的第三个参数是 childKey。它被称为 with ,nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar
因为它是里面的第三个参数traverseAllChildrenImpl
。
SEPARATOR = "."
并getComponentKey
在转义函数中返回带有 $ 前缀的键。
更新的问题:
现在我正在寻找解决这个问题的方法......我不确定是否有人考虑使用空字符串调用 traverseAllChildrenImpl 作为nameSoFar
内的 traverseAllChildren。
我认为这可能是React.Children.map
构建新 DOM的预期行为。当我尝试更新动态孩子的props时,这对我造成了影响。
解决方案:不要使用它们不打算使用的方式。
我正在构建一组对开发人员来说非常容易的表单控件。状态树是通过映射子节点和使用 . 从具有名称的元素中划定字符串名称以在顶级组件上创建键和值。
顶级表单组件具有用于不同类型控件的 onChange 处理程序,它们根据需要应用于元素的 onChange 属性。这个映射是在 componentWillMount 方法中完成的,是导致我出现问题的原因。
将映射移动到渲染方法允许我不必更新句柄中的子项。更新句柄会导致元素失去焦点。现在一切都很好!