ReactJs:this.props.children 的 PropTypes 应该是什么?
ReactJs: What should the PropTypes be for this.props.children?
给定一个呈现其 children:
的简单组件
class ContainerComponent extends Component {
static propTypes = {
children: PropTypes.object.isRequired,
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default ContainerComponent;
问题:children prop的propType应该是什么?
当我将其设置为 object 时,当我将组件与多个 children:
一起使用时,它会失败
<ContainerComponent>
<div>1</div>
<div>2</div>
</ContainerComponent>
Warning: Failed prop type: Invalid prop children
of type array
supplied to ContainerComponent
, expected object
.
如果我将它设置为一个数组,如果我只给它一个child,它就会失败,即:
<ContainerComponent>
<div>1</div>
</ContainerComponent>
Warning: Failed prop type: Invalid prop children of type object
supplied to ContainerComponent, expected array.
请指教,我是不是应该为 children 元素做一个 propTypes 检查?
使用 oneOfType
或 PropTypes.node
尝试类似的操作
import PropTypes from 'prop-types'
...
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
}
或
static propTypes = {
children: PropTypes.node.isRequired,
}
尝试自定义 propTypes :
const childrenPropTypeLogic = (props, propName, componentName) => {
const prop = props[propName];
return React.Children
.toArray(prop)
.find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
};
static propTypes = {
children : childrenPropTypeLogic
}
const {Component, PropTypes} = React;
const childrenPropTypeLogic = (props, propName, componentName) => {
var error;
var prop = props[propName];
React.Children.forEach(prop, function (child) {
if (child.type !== 'div') {
error = new Error(
'`' + componentName + '` only accepts children of type `div`.'
);
}
});
return error;
};
class ContainerComponent extends Component {
static propTypes = {
children: childrenPropTypeLogic,
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
class App extends Component {
render(){
return (
<ContainerComponent>
<div>1</div>
<div>2</div>
</ContainerComponent>
)
}
}
ReactDOM.render(<App /> , document.querySelector('section'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<section />
对我来说,这取决于组件。如果您知道需要填充什么,那么您应该尝试使用以下方式专门指定或指定多种类型:
PropTypes.oneOfType
如果你想引用 React 组件,那么你将寻找
PropTypes.element
虽然,
PropTypes.node
描述任何可以呈现的东西——字符串、数字、元素或这些东西的数组。如果这适合你,那么就是这样。
有了非常的泛型组件,谁可以有很多类型children,你也可以使用下面的。但是我不推荐它。正如下面的评论中所提到的,它确实在某种程度上破坏了使用 PropTypes
的意义,并且通常还有其他方法可以指定您的组件需要什么。还要记住,eslint 和 ts 可能(可能)对这种缺乏特异性不满意:
PropTypes.any
如果你想精确匹配一个组件类型,勾选这个
MenuPrimary.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(MenuPrimaryItem),
PropTypes.objectOf(MenuPrimaryItem)
])
}
如果您想精确匹配某些组件类型,请选中此
const HeaderTypes = [
PropTypes.objectOf(MenuPrimary),
PropTypes.objectOf(UserInfo)
]
Header.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
...HeaderTypes
])
}
这里的答案似乎并没有完全涵盖 children 的检查。 node
和 object
太宽容了,我想检查确切的元素。这是我最终使用的:
- 使用
oneOfType([])
允许单个或数组children
- 对children的单个和数组分别使用
shape
和arrayOf(shape({}))
- 对 child 元素本身使用
oneOf
最后是这样的:
import PropTypes from 'prop-types'
import MyComponent from './MyComponent'
children: PropTypes.oneOfType([
PropTypes.shape({
type: PropTypes.oneOf([MyComponent]),
}),
PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.oneOf([MyComponent]),
})
),
]).isRequired
这个问题帮助我更清楚地解决了这个问题:https://github.com/facebook/react/issues/2979
The PropTypes documentation 有以下
// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,
因此,您可以使用 PropTypes.node
检查对象或对象数组
static propTypes = {
children: PropTypes.node.isRequired,
}
示例:
import React from 'react';
import PropTypes from 'prop-types';
class MenuItem extends React.Component {
render() {
return (
<li>
<a href={this.props.href}>{this.props.children}</a>
</li>
);
}
}
MenuItem.defaultProps = {
href: "/",
children: "Main page"
};
MenuItem.propTypes = {
href: PropTypes.string.isRequired,
children: PropTypes.string.isRequired
};
export default MenuItem;
图片:如果预期类型不同,会在控制台中显示错误
如果你想包含渲染道具组件:
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
PropTypes.func
])
根据propTypes documentation element
用于React元素,children是其中之一:
// A React element.
optionalElement: PropTypes.element,
然后可以和arrayOf
结合
Component.propTypes = {
children: PropTypes.arrayOf(PropTypes.element).isRequired,
};
那么至少需要一个children
.
给定一个呈现其 children:
的简单组件class ContainerComponent extends Component {
static propTypes = {
children: PropTypes.object.isRequired,
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default ContainerComponent;
问题:children prop的propType应该是什么?
当我将其设置为 object 时,当我将组件与多个 children:
一起使用时,它会失败<ContainerComponent>
<div>1</div>
<div>2</div>
</ContainerComponent>
Warning: Failed prop type: Invalid prop
children
of typearray
supplied toContainerComponent
, expectedobject
.
如果我将它设置为一个数组,如果我只给它一个child,它就会失败,即:
<ContainerComponent>
<div>1</div>
</ContainerComponent>
Warning: Failed prop type: Invalid prop children of type object supplied to ContainerComponent, expected array.
请指教,我是不是应该为 children 元素做一个 propTypes 检查?
使用 oneOfType
或 PropTypes.node
import PropTypes from 'prop-types'
...
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
}
或
static propTypes = {
children: PropTypes.node.isRequired,
}
尝试自定义 propTypes :
const childrenPropTypeLogic = (props, propName, componentName) => {
const prop = props[propName];
return React.Children
.toArray(prop)
.find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
};
static propTypes = {
children : childrenPropTypeLogic
}
const {Component, PropTypes} = React;
const childrenPropTypeLogic = (props, propName, componentName) => {
var error;
var prop = props[propName];
React.Children.forEach(prop, function (child) {
if (child.type !== 'div') {
error = new Error(
'`' + componentName + '` only accepts children of type `div`.'
);
}
});
return error;
};
class ContainerComponent extends Component {
static propTypes = {
children: childrenPropTypeLogic,
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
class App extends Component {
render(){
return (
<ContainerComponent>
<div>1</div>
<div>2</div>
</ContainerComponent>
)
}
}
ReactDOM.render(<App /> , document.querySelector('section'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<section />
对我来说,这取决于组件。如果您知道需要填充什么,那么您应该尝试使用以下方式专门指定或指定多种类型:
PropTypes.oneOfType
如果你想引用 React 组件,那么你将寻找
PropTypes.element
虽然,
PropTypes.node
描述任何可以呈现的东西——字符串、数字、元素或这些东西的数组。如果这适合你,那么就是这样。
有了非常的泛型组件,谁可以有很多类型children,你也可以使用下面的。但是我不推荐它。正如下面的评论中所提到的,它确实在某种程度上破坏了使用 PropTypes
的意义,并且通常还有其他方法可以指定您的组件需要什么。还要记住,eslint 和 ts 可能(可能)对这种缺乏特异性不满意:
PropTypes.any
如果你想精确匹配一个组件类型,勾选这个
MenuPrimary.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(MenuPrimaryItem),
PropTypes.objectOf(MenuPrimaryItem)
])
}
如果您想精确匹配某些组件类型,请选中此
const HeaderTypes = [
PropTypes.objectOf(MenuPrimary),
PropTypes.objectOf(UserInfo)
]
Header.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
...HeaderTypes
])
}
这里的答案似乎并没有完全涵盖 children 的检查。 node
和 object
太宽容了,我想检查确切的元素。这是我最终使用的:
- 使用
oneOfType([])
允许单个或数组children - 对children的单个和数组分别使用
shape
和arrayOf(shape({}))
- 对 child 元素本身使用
oneOf
最后是这样的:
import PropTypes from 'prop-types'
import MyComponent from './MyComponent'
children: PropTypes.oneOfType([
PropTypes.shape({
type: PropTypes.oneOf([MyComponent]),
}),
PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.oneOf([MyComponent]),
})
),
]).isRequired
这个问题帮助我更清楚地解决了这个问题:https://github.com/facebook/react/issues/2979
The PropTypes documentation 有以下
// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,
因此,您可以使用 PropTypes.node
检查对象或对象数组
static propTypes = {
children: PropTypes.node.isRequired,
}
示例:
import React from 'react';
import PropTypes from 'prop-types';
class MenuItem extends React.Component {
render() {
return (
<li>
<a href={this.props.href}>{this.props.children}</a>
</li>
);
}
}
MenuItem.defaultProps = {
href: "/",
children: "Main page"
};
MenuItem.propTypes = {
href: PropTypes.string.isRequired,
children: PropTypes.string.isRequired
};
export default MenuItem;
图片:如果预期类型不同,会在控制台中显示错误
如果你想包含渲染道具组件:
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
PropTypes.func
])
根据propTypes documentation element
用于React元素,children是其中之一:
// A React element.
optionalElement: PropTypes.element,
然后可以和arrayOf
Component.propTypes = { children: PropTypes.arrayOf(PropTypes.element).isRequired, };
那么至少需要一个children
.