Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Validation 在react组件中仅允许特定类型的子级_Validation_Reactjs - Fatal编程技术网

Validation 在react组件中仅允许特定类型的子级

Validation 在react组件中仅允许特定类型的子级,validation,reactjs,Validation,Reactjs,我有一个Card组件和一个CardGroup组件,当CardGroup有一个子组件不是Card组件时,我想抛出一个错误。这是可能的,还是我试图解决错误的问题?您可以为每个子级使用displayName,通过键入: for (child in this.props.children){ if (this.props.children[child].type.displayName != 'Card'){ console.log("Warning CardGroup has childr

我有一个
Card
组件和一个
CardGroup
组件,当
CardGroup
有一个子组件不是
Card
组件时,我想抛出一个错误。这是可能的,还是我试图解决错误的问题?

您可以为每个子级使用displayName,通过键入:

for (child in this.props.children){
  if (this.props.children[child].type.displayName != 'Card'){
    console.log("Warning CardGroup has children that aren't Card components");
  }  
}

您可以使用自定义propType函数来验证子项,因为子项只是道具。我也写了一篇关于这个的文章,如果你想了解更多细节的话

var CardGroup=React.createClass({
道具类型:{
子项:函数(props、propName、componentName){
var误差;
var prop=props[propName];
React.Children.forEach(道具,函数(子对象){
if(child.type.displayName!=='Card'){
错误=新错误(
“`+componentName+``只接受“Card”类型的子项
);
}
});
返回误差;
}
},
渲染:函数(){
返回(
{this.props.children}
);
}
});

对于React 0.14+和使用ES6类,解决方案如下所示:

class CardGroup扩展组件{
render(){
返回(
{this.props.children}
)
}
}
CardGroup.propTypes={
子项:函数(props、propName、componentName){
const prop=props[propName]
let error=null
React.Children.forEach(道具,函数(子对象){
if(child.type!==卡){
error=新错误('`+componentName+'`子项应为'Card'类型);
}
})
返回错误
}
}

我为此制作了一个自定义的PropType,我称之为
equalTo
。你可以这样使用它

类MyChildComponent扩展了React.Component{…} 类MyParentComponent扩展了React.Component{ 静态类型={ 子类:PropTypes.arrayOf(PropTypes.equalTo(MyChildComponent)) } } 现在,
MyParentComponent
只接受属于
MyChildComponent
的子级。您可以检查像这样的html元素

PropTypes.equalTo('h1'))
PropTypes.equalTo('div')
PropTypes.equalTo('img'))
...
这里是实现

React.PropTypes.equalTo=函数(组件){
返回函数验证(propValue、键、组件名、位置、propFullName){
常量属性=属性值[键]
if(道具类型!==组件){
返回新错误(
“提供给”的“无效的prop`+propFullName+''+
“`+componentName+`。验证失败。”
);
}
};
}
您可以很容易地扩展它以接受多种可能的类型之一。也许像

React.PropTypes.equalToOneOf=函数(ArrayFaceptedComponents){
...
}

我发布了允许验证React元素类型的包:

const-ElementPropTypes=require('react-element-proptypes');
常量模态=({头,项})=>(
{header}
{items}
);
Modal.propTypes={
标题:ElementPropTypes.elementOfType(标题)。需要,
items:React.PropTypes.arrayOf(ElementPropTypes.elementOfType(Item))
};
//渲染模态
反应(
,
根元素
);
静态属性类型={
子项:(props、propName、componentName)=>{
const prop=props[propName];
回来,孩子们
.托雷(道具)
.find(child=>child.type!==Card)&&new错误(`${componentName}只接受“”元素`);
},
}

您可以在
卡组件中添加一个道具,然后在
卡组组件中检查该道具。这是在React中实现这一点最安全的方法

此道具可以作为默认道具添加,因此它始终存在

class Card extends Component {

  static defaultProps = {
    isCard: true,
  }

  render() {
    return (
      <div>A Card</div>
    )
  }
}

class CardGroup extends Component {

  render() {
    for (child in this.props.children) {
      if (!this.props.children[child].props.isCard){
        console.error("Warning CardGroup has a child which isn't a Card component");
      }
    }

    return (
      <div>{this.props.children}</div>
    )
  }
}
类卡扩展组件{
静态defaultProps={
是的,
}
render(){
返回(
卡片
)
}
}
类CardGroup扩展组件{
render(){
for(此.props.children中的children){
如果(!this.props.children[child].props.isCard){
console.error(“警告CardGroup有一个子项不是卡组件”);
}
}
返回(
{this.props.children}
)
}
}

使用
type
displayName
检查卡组件是否确实是卡组件是不安全的,因为它可能在生产使用期间不起作用,如下所示:

适用于使用TypeScript版本的用户。 您可以像这样过滤/修改组件:

this.modifiedChildren = React.Children.map(children, child => {
            if (React.isValidElement(child) && (child as React.ReactElement<any>).type === Card) {
                let modifiedChild = child as React.ReactElement<any>;
                // Modifying here
                return modifiedChild;
            }
            // Returning other components / string.
            // Delete next line in case you dont need them.
            return child;
        });
this.modifiedChildren=React.Children.map(Children,child=>{
if(React.isValidElement(子项)和&(子项作为React.ReactElement.type==Card){
将modifiedChild=子级作为React.ReactElement;
//在这里修改
返回修改过的孩子;
}
//返回其他组件/字符串。
//删除下一行,以防不需要它们。
返回儿童;
});
如果使用Typescript,则必须使用“React.isValidElement(child)”和“child.type”,以避免类型不匹配错误

React.Children.forEach(props.children, (child, index) => {
  if (React.isValidElement(child) && child.type !== Card) {
    error = new Error(
      '`' + componentName + '` only accepts children of type `Card`.'
    );
  }
});

为了验证正确的子组件,我结合了和的使用,因此最后您可以有以下内容:

HouseComponent.propTypes = {
children: PropTypes.oneOfType([(props, propName, componentName) => {
    let error = null;
    const validInputs = [
    'Mother',
    'Girlfried',
    'Friends',
    'Dogs'
    ];
    // Validate the valid inputs components allowed.
    React.Children.forEach(props[propName], (child) => {
            if (!validInputs.includes(child.type.name)) {
                error = new Error(componentName.concat(
                ' children should be one of the type:'
                    .concat(validInputs.toString())
            ));
        }
    });
    return error;
    }]).isRequired
};
正如您所看到的,具有正确类型名称的和数组

另一方面,airbnb/prop类型库中还有一个名为componentWithName的函数,有助于获得相同的结果。


希望这对某些人有所帮助:)

使用
React.Children.forEach
方法迭代子项,并使用
name
属性检查类型:

React.Children.forEach(this.props.children, (child) => {
    if (child.type.name !== Card.name) {
        console.error("Only card components allowed as children.");
    }
}
props.children.forEach(child =>
  console.assert(
    child.type.name == "CanvasItem",
    "CanvasScroll can only have CanvasItem component as children."
  )
)
我建议使用
Card.name
而不是
'Card'
字符串,以便更好地维护和稳定丑陋的车辆


请参阅:

对我来说,实现这一点的最简单方法是以下代码

示例1:

import React, {Children} from 'react';

function myComponent({children}) {

  return (
    <div>{children && Children.map(children, child => {
      if (child.type === 'div') return child
    })}</div>
  )
}

export default myComponent;
import React,{Children}来自'React';
功能部件({
React.Children.forEach(this.props.children, (child) => {
    if (child.type.name !== Card.name) {
        console.error("Only card components allowed as children.");
    }
}
import React, {Children} from 'react';

function myComponent({children}) {

  return (
    <div>{children && Children.map(children, child => {
      if (child.type === 'div') return child
    })}</div>
  )
}

export default myComponent;
import React, {Children} from 'react';

function myComponent({children}) {

  return (
    <div>{children && Children.map(children, child => {
      if (child.type.displayName === 'Card') return child
    })}</div>
  )
}

export default myComponent;
props.children.forEach(child =>
  console.assert(
    child.type.name == "CanvasItem",
    "CanvasScroll can only have CanvasItem component as children."
  )
)