只允许react组件中特定类型的子项

IT技术 validation reactjs
2021-04-20 02:17:15

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

6个回答

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

class CardGroup extends Component {
  render() {
    return (
      <div>{this.props.children}</div>
    )
  }
}
CardGroup.propTypes = {
  children: function (props, propName, componentName) {
    const prop = props[propName]

    let error = null
    React.Children.forEach(prop, function (child) {
      if (child.type !== Card) {
        error = new Error('`' + componentName + '` children should be of type `Card`.');
      }
    })
    return error
  }
}
@user2167582 因为这是道具验证功能的预期 API。官方文档在示例代码中包含以下注释:您还可以指定自定义验证器。如果验证失败,它应该返回一个 Error 对象。不要console.warn或扔,因为这在里面不起作用oneOfType
2021-06-02 02:17:15
的文档在哪里child.type有人可以发链接吗?
2021-06-02 02:17:15
这对我有用 React.Children.forEach(props[propName], function (child) { if (child.type && child.type.name !== 'Card') { error = new Error('Blabla ´' + componentName + '一些错误'); } })
2021-06-07 02:17:15
为什么不立即抛出它,而不是返回一个 Error 值。
2021-06-14 02:17:15
我不知道为什么,但child.type === Card在我的设置中不起作用。但是我通过使用child.type.prototype instanceof Card. 我的 React 版本是 15.5.4
2021-06-15 02:17:15

您可以为每个孩子使用 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");
  }  
}
但请记住,使用 Uglify 之类的东西会破坏这一点
2021-05-23 02:17:15
确保检查当前环境是开发环境还是生产环境。propTypes 验证不会在生产中触发以提高性能。在 propTypes 中使用 customProp 会很有帮助。
2021-06-13 02:17:15
那“帮助了我”,但我使用了name而不是displayName(最后一个对我不起作用)
2021-06-14 02:17:15
永远不要使用 displayName 因为在生产中它可能会被删除!
2021-06-18 02:17:15
您不应该这样做,因为它props.children是一种不透明的数据类型更好地利用React.Children公用事业如图所示这里
2021-06-19 02:17:15

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

var CardGroup = React.createClass({
  propTypes: {
    children: function (props, propName, componentName) {
      var error;
      var prop = props[propName];

      React.Children.forEach(prop, function (child) {
        if (child.type.displayName !== 'Card') {
          error = new Error(
            '`' + componentName + '` only accepts children of type `Card`.'
          );
        }
      });

      return error;
    }
  },

  render: function () {
    return (
      <div>{this.props.children}</div>
    );
  }
});
我也喜欢这种语法,但类属性仍然只是 ES7 的一个提议。就个人而言,我会等着看它是否标准化:)
2021-05-30 02:17:15
这个语法对 ES2015 和 React 0.14.x+ 仍然有效吗?
2021-06-11 02:17:15
谢谢,@DiegoV。我认为您也可以static propTypes = {}在类定义中声明
2021-06-19 02:17:15
child.type.displayName 混淆后不起作用
2021-06-21 02:17:15

使用该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.");
    }
}

我建议使用Card.name代替'Card'string 来更好地维护和稳定uglify

请参阅:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

仅当我将名称更改为 displayName if (child.type.displayName !== Card.name) 时才有效
2021-06-09 02:17:15

对于那些使用 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;
        });