Javascript 使用非元素子元素的子元素
给定组件作为子对象接收函数(回调作为子模式,也称为渲染属性模式):Javascript 使用非元素子元素的子元素,javascript,reactjs,Javascript,Reactjs,给定组件作为子对象接收函数(回调作为子模式,也称为渲染属性模式): {()=>} Foo中的React.Children.count(props.Children)==0 文档似乎没有提到React.Children只接受有效的React元素,因此忽略子函数这一事实看起来很奇怪 如何反应。儿童治疗非元素儿童,为什么 欢迎参考官方来源和/或源代码。更新: 免责声明:这不是一个解决方案,只是一个我们可以看到的眼睛 我不确定,但如果确实需要在React中对其进行修复,那么我建议更改以下函数: 此代
{()=>}
Foo中的React.Children.count(props.Children)==0
文档似乎没有提到React.Children
只接受有效的React元素,因此忽略子函数这一事实看起来很奇怪
如何反应。儿童
治疗非元素儿童,为什么
欢迎参考官方来源和/或源代码。更新:
免责声明:这不是一个解决方案,只是一个我们可以看到的眼睛
我不确定,但如果确实需要在React中对其进行修复,那么我建议更改以下函数:
此代码:
typeof object === 'object'
例如:
typeof Object.create(object) === 'object'
Symbol.for('react.function')
并为以下内容添加一个符号:
typeof Object.create(object) === 'object'
Symbol.for('react.function')
在公园里
当前用于计算具有以下项的子项的解决方案:
这使您可以将函数作为子组件计算为子组件this.props.children
包括任何类型的元素、表达式或组件,而this.props.children
内部会做出反应。children
作为子元素的功能将作为子元素被忽略。继续阅读下面的内容以更好地理解它
switch (type) {
case 'string':
case 'number':
invokeCallback = true;
break;
case 'object':
switch (children.$$typeof) {
case REACT_ELEMENT_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
}
}
if (invokeCallback) {
// Other code
return 1;
}
这是一个例子
Read不把函数视为子组件。
然而,我刚刚提交了一个问题,如果你愿意,你可以
指定React.Children.count
仅对子级中的组件进行计数
您可能已经知道确切的含义。
React将所有内容作为子对象,但函数作为子对象
以下是参考文件,其中说明:
React组件不支持作为子级的功能
如果你愿意,你可以看得更深一些
所以,在
组件中有一个作为子函数的函数,所以它确实返回0,因为它不被视为子函数
您可以选择将这些表达式计算为其子表达式,然后可以先将它们转换为数组,然后进行如下计算:
class CountExpression extends React.Component {
render() {
const children = React.Children.toArray(this.props.children)
return <p>{React.Children.count(children)}</p>
}
}
{ /* Counts 2 */ }
<CountExpression>
{'one'}
{'two'}
{ () => <p>Still, this will be ignored as child and is not included in array</p>}
</CountExpression>
如果有更多的子项,那么它只是在控制台中显示警告,然后让程序执行下一步
好:
class OnlyChildComponent extends React.Component {
render() {
return this.props.children()
}
}
{ /* Enforcing it as a single child component */ }
OnlyChildComponent.propTypes = {
children: React.PropTypes.func.isRequired
}
class OnlyChildComponent extends React.Component {
render() {
return React.Children.only(this.props.children)()
}
}
如果有多个孩子,那么它将抛出一个错误!它会停止程序的执行。避免弄乱我们的组件非常好。正如其他人所说,React.Children.count(Children)
的状态只返回有效的React
组件的子级数目的计数
React.Children
不会忽略其他类型的子对象,如果需要获取计数,只需确定根子对象中数组的长度,就像在vanilla js中一样。如果您查看,您将看到它们指定子项
必须是func
的类型:
Mouse.propTypes = {
children: PropTypes.func.isRequired
};
他们进一步确保只有一个孩子有React.Children.only
():
React不会单独处理不同类型的孩子,相反,你必须自己处理他们。我放了一个例子来告诉你原因。根据:
React.Children.count返回子级中组件的总数,等于
传递给map或forEach的回调将被调用的次数
调用
上面语句的意思是,如果传递给组件的子元素是可迭代的,那么只有计数会增加
const iteratorFn = getIteratorFn(children);
if (typeof iteratorFn === 'function') {
现在让我们看一下内部用于计算计数的代码片段
React.children.count
使用
主要代码是
function traverseAllChildren(children, callback, traverseContext) {
if (children == null) {
return 0;
}
return traverseAllChildrenImpl(children, '', callback, traverseContext);
}
因此,如果children
为null
,则返回0
函数遍历alChildrenImpl(
儿童
命名法,
回拨,
通过文本,
) {
switch (type) {
case 'string':
case 'number':
invokeCallback = true;
break;
case 'object':
switch (children.$$typeof) {
case REACT_ELEMENT_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
}
}
if (invokeCallback) {
// Other code
return 1;
}
因此从上面的代码我们推断我们的孩子是String
,Number
它将返回1
继续下一部分
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
child = children[i];
nextName = nextNamePrefix + getComponentKey(child, i);
subtreeCount += traverseAllChildrenImpl(
child,
nextName,
callback,
traverseContext,
);
}
}
对于作为可迭代的子函数提供的函数(如映射),它将遍历元素并计算子树计数
对于对象,它将返回一个错误
invariant(
false,
'Objects are not valid as a React child (found: %s).%s',
childrenString === '[object Object]'
? 'object with keys {' + Object.keys(children).join(', ') + '}'
: childrenString,
addendum,
);
上述信息的演示在TLDR中
从:
React.Children
提供了处理this.props.Children
不透明数据结构的实用程序
换句话说,React.Children
名称空间中充满了实用函数,当在中使用this.props.Children
实现其主要目的时,这些函数非常有用
合成模型使用特殊的children
属性处理可以直接渲染到父组件输出中的内容,因此像React.children.count
这样的实用函数被编程为只包含可以直接渲染的内容
由于函数不能直接呈现到父组件的输出中,因此它不包括在React.Children.count
的结果中
什么是儿童道具?
children
道具是一种特殊道具,用于将组件传递给其子组件
我相信你也知道
的呼叫签名如下所示:
React.createElement(类型、道具、子项)
因此,当组件在JSX中传递子级时,如下所示:
孩子1
孩子2
…它产生以下代码:
React.createElement(Foo,null,
React.createElement(“div”,null,“child1”),
React.createElement(“div”,null,“child2”)
);
…其中子项作为尾随参数传递,并在组件中作为特殊的子项
属性提供
孩子们的道具是什么?
儿童
道具是一种特殊道具
switch (type) {
case 'string':
case 'number':
invokeCallback = true;
break;
case 'object':
switch (children.$$typeof) {
case REACT_ELEMENT_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
}
}
if (invokeCallback) {
// Other code
return 1;
}
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
child = children[i];
nextName = nextNamePrefix + getComponentKey(child, i);
subtreeCount += traverseAllChildrenImpl(
child,
nextName,
callback,
traverseContext,
);
}
}
const iteratorFn = getIteratorFn(children);
if (typeof iteratorFn === 'function') {
invariant(
false,
'Objects are not valid as a React child (found: %s).%s',
childrenString === '[object Object]'
? 'object with keys {' + Object.keys(children).join(', ') + '}'
: childrenString,
addendum,
);