Kyl*_*son 4 javascript reactjs
正如标题所述,使用React.cloneElementinside React.Children.map会导致元素键发生变化.
这是一个展示这个的沙箱.
React.Children.map(children, (child) => {
let clonedEl = React.cloneElement( child );
console.log(clonedEl);
return clonedEl;
});
Run Code Online (Sandbox Code Playgroud)
该代码块的结果具有.$添加到每个键前面的元素.由于两个原因,这实在令人困惑.
1:文档说cloneElement将保留密钥和引用.
使用element作为起点克隆并返回一个新的React元素.结果元素将具有原始元素的道具,新道具以浅层方式合并.新的孩子将取代现有的孩子.key和ref将保留原始元素.
2:结果console.log是一个保留键和ref的元素...
这会让我相信在React.Children.map代码中的某处发生了添加.
更新:看完React.Children.map的代码后......
我发现它是由以下函数链添加的:mapChilren - > mapIntoWithKeyPrefixInternal - > traverseAllChildren - > traverseAllChildrenImpl - > mapSingleChildIntoContext.
mapSingleChildIntoContext第三个参数是childKey.它被称为nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar内部的第三个参数traverseAllChildrenImpl.
SEPARATOR = "."并getComponentKey在escape函数中返回带有$前缀的键.
更新的问题:
现在我正在寻找解决这个问题的方法...我不确定是否有一个考虑traverseAllChildrenImpl被调用,其中一个空字符串作为nameSoFartraverseAllChildren.
我认为这可能是React.Children.map构建新DOM 的预期行为.在尝试更新动态子项上的道具时,这对我来说是个问题.
解决方案:不要使用不打算使用的东西.
我正在构建一组表单控件,这对开发人员来说非常容易.状态树是通过映射子项和使用来动态构建的.从具有名称的元素描绘字符串名称,以在顶级组件上创建键和值.
顶级表单组件具有用于不同类型控件的onChange处理程序,它们根据需要应用于元素的onChange属性.这个映射是在componentWillMount方法中完成的,这也是导致我出现问题的原因.
将映射移动到render方法允许我不必更新句柄中的子项.句柄中的更新导致元素失去焦点.一切都很好!
问题不cloneElement在于改变你的密钥.如文档中所述,cloneElement保留原始密钥.它为React.Children.map它添加了一个前缀.如果您不希望更改密钥forEach而不是使用map
这是React Code的摘录:
function escape(key) {
var escapeRegex = /[=:]/g;
var escaperLookup = {
'=': '=0',
':': '=2',
};
var escapedString = ('' + key).replace(escapeRegex, function(match) {
return escaperLookup[match];
});
return '$' + escapedString;
}
function getComponentKey(component, index) {
// Do some typechecking here since we call this blindly. We want to ensure
// that we don't block potential future ES APIs.
if (
typeof component === 'object' &&
component !== null &&
component.key != null
) {
// Explicit key
return escape(component.key);
}
// Implicit key determined by the index in the set
return index.toString(36);
}
function mapSingleChildIntoContext(bookKeeping, child, childKey) {
var {result, keyPrefix, func, context} = bookKeeping;
var mappedChild = func.call(context, child, bookKeeping.count++);
if (Array.isArray(mappedChild)) {
mapIntoWithKeyPrefixInternal(
mappedChild,
result,
childKey,
emptyFunction.thatReturnsArgument,
);
} else if (mappedChild != null) {
if (ReactElement.isValidElement(mappedChild)) {
mappedChild = ReactElement.cloneAndReplaceKey(
mappedChild,
// Keep both the (mapped) and old keys if they differ, just as
// traverseAllChildren used to do for objects as children
keyPrefix +
(mappedChild.key && (!child || child.key !== mappedChild.key)
? escapeUserProvidedKey(mappedChild.key) + '/'
: '') +
childKey,
);
}
result.push(mappedChild);
}
}
function mapChildren(children, func, context) {
if (children == null) {
return children;
}
var result = [];
mapIntoWithKeyPrefixInternal(children, result, null, func, context);
return result;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2658 次 |
| 最近记录: |