Skip to content

Conversation

@alansouzati
Copy link
Contributor

In short, this PR aims to provide support for Single Child of a given type.

From the official ReactJS docs page we can use React.PropTypes.element to validate a single child.

With React.PropTypes.element you can specify that only a single child can be passed to a component as children.

I tried to find something that would validate the type of the given element, but it seems that it is not possible as of today.

With this PR you can do:

Component.propTypes = {
  testProp: React.PropTypes.elementOfType('svg').isRequired
};

@aweary
Copy link
Contributor

aweary commented Jun 24, 2016

This might be something that's better suited as a separate library, as @jimfb has mentioned in the past:

Proptypes are mostly legacy and in maintenance mode right now. We don't want to increase the surface area of proptypes at the moment, if we can avoid it.

@alansouzati
Copy link
Contributor Author

I can definitely put this into a separate library.

I took a look in the map PR and it seems that there is an easy alternative away to achieve the same thing with:

PropTypes.instanceOf(Set)
PropTypes.instanceOf(WeakSet)
PropTypes.instanceOf(Map)
PropTypes.instanceOf(WeakMap)

I don't think this is the case with elementOf.

I'm trying to avoid to maintain yet another library, and I believe elementOf is close enough to element and does not extend much the API surface area.

I will give it a few days, if this is the common agreement in the community I can pull this off into a library.

Thanks for the fast response here @aweary

@alansouzati
Copy link
Contributor Author

@gaearon and @jimfb it would be great if you could weight in here 👍

@gaearon
Copy link
Collaborator

gaearon commented Jun 26, 2016

My personal opinion is that requiring elements to be of a specific type is an antipattern more often than not. I’m not saying it never happens, but it encourages tightly coupling components and makes it harder to introduce “transparent” wrappers around children.

So while there may be use cases for this, I would say we’d rather not encourage this pattern, and it would better live as a third party library. Additionally we are very hesitant to expand the surface API area of PropTypes which we plan to eventually extract from React.

For these two reasons I’m closing this. Thanks for taking the time to do a PR!

@gaearon gaearon closed this Jun 26, 2016
@alansouzati
Copy link
Contributor Author

Thanks for the follow-up guys. I have an Icon component that must have a svg as a child so that I can augment it with accessibility features.

I thought about sending the SVG as prop. If it is a property we have a way to validate the prop type.

My question is: why the same validation is not present for children? I'm confused when I should send as a property and when I should use children. And why it is ok to validade the property type, but it is not ok/recommended to validate the children type.

I would really appreciate any pointers to help me follow the react best practices.

@gaearon
Copy link
Collaborator

gaearon commented Jun 27, 2016

I'm not sure I understand you. Children are a prop. There is nothing preventing you from validating the type of the children prop. It's not any different from any other prop.

I'm just saying that I wouldn't recommend using a validation strategy like elementOf. Neither for children prop nor for other props.

If you don't know which type of element you want the user to pass, it's best not to enforce it. If you already which type of element you expect user to pass, why pass it in the first place? Let user put props directly on your component instead of passing a child of a single allowed type.

It's hard to say more without a code example of how you'd want to use this feature.

@alansouzati
Copy link
Contributor Author

Sorry about the confusion about children vs props. This is an example of what I'm trying to achieve.

  1. An icon component that can receive a raw SVG an augment it with features (e.g accessibility)

Icon

  const Icon = () => {
    return (
       <svg {...this.props.children.props} className="control-icon" role="img">
          <title>{this.props.title}</title>
          {this.props.children.props.children}
       </svg>
    );
  };

Usage

  <Icon title="Custom Icon">
    <svg>
      ...
    </svg>
  </Icon>

I was trying to add a validation to the Icon component to make sure that there is always one children with the type of SVG. So, from I what I understand of your recommendation, I believe you are saying that Icon component should be able to handle the SVG properties itself, and the children of the Icon component should be the SVG paths and elements. Is that correct?

Recommendation:

Icon

  const Icon = () => {
    return (
       <svg {...this.props} className="control-icon" role="img">
          <title>{this.props.title}</title>
          {this.props.children}
       </svg>
    );
  };

Usage

 <Icon title="Custom Icon">
      ...
  </Icon>

I believe it makes totally sense, and thanks for the guidelines.

At the end, I don't think this is related at all to react best practices, but to composition in general. Thanks for being open to discuss that regardless.

@gaearon
Copy link
Collaborator

gaearon commented Jun 27, 2016

Yep, your later example is exactly what I meant. Glad we figured it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants