-
Notifications
You must be signed in to change notification settings - Fork 354
Conversation
Technically this is an element, not a component - it's similar to |
README.md
Outdated
@@ -89,11 +91,14 @@ MyComponent.propTypes = { | |||
// it as an enum. | |||
optionalEnum: PropTypes.oneOf(['News', 'Photos']), | |||
|
|||
optionalElementOfType: PropTypes.elementOfType(['div', OtherComponent]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why allow it to take an array of types instead of a single one? PropTypes.oneOfType
is the established way to compose multiple validators.
Separately, I think "oneOf" is always in the name when it's taking an array of multiples; thus, I think elementOfType
taking one, or oneOfElementType
taking an array, is what would make sense - and I think the latter sounds silly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specific problem I'm trying to solve is the oneOfType scenario, but considering the need to whitelist more than one type of components:
<CustomTable>
<CustomHeader/>
<CustomTableRow/>
<CustomTableRow/>
<CustomTableRow/>
<CustomFooter/>
</CustomTable>
// this is what I'm looking for
CustomTable.propTypes = {
children: elementsOfType([CustomHeader, CustomTableRow, CustomFooter])
}
or
<SVGSection>
<use/>
<g></g>
<rectangle/>
<CustomSvgLine />
</SVGSection>
SVGSection.propTypes = {
children: elementsOfType([ ...SVG_CHILDREN, ...MY_CUSTOM_SVG_CHILDREN ])
}
I'm hoping to capture these use cases so that when allow reusability of component, I'm always covered by this type checker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PropTypes.oneOfType([ ...SVG_CHILDREN, ...MY_CUSTOM_SVG_CHILDREN ].map(x => PropType.elementOfType(x)))
works just fine, without overcomplicating the propType validator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb that sounds reasonable, I will make the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb fyi, one feature we will lose from this change is a error message that says expected one of type [div, span, CustomComponent]
, if we use oneOfType
, we will only be seeing the generic message Invalid prop supplied ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there’s a way oneOfType can read info off of the validators it receives to improve the error message, but I’m not sure what it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb i wonder how that would work if each proptype returns a different error message.
factoryWithTypeCheckers.js
Outdated
} | ||
|
||
function validate(props, propName, componentName, location, propFullName) { | ||
expectedTypes = [].concat(expectedTypes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should throw if expectedTypes
isn't an array (if it takes an array), like oneOf
/oneOfType
do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm hoping to give user some flexibility in case they only want to pass a single expected element type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flexibility in APIs leads to bugs; if they want to pass a single type, they can add [ ]
without difficulty.
@@ -871,6 +871,82 @@ describe('PropTypesDevelopmentStandalone', () => { | |||
}); | |||
}); | |||
|
|||
describe('ElementOfType Types', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, ‘of type” implies it receives propType validators; i think this should be called “elementOf”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are really checking if the given object has a .type
attribute that matches the given accepted, hows ElementWithType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or maybe just elementType
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, there's already a createElementTypeChecker
which is a little bit confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createElementTypeTypeChecker :-D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test case that fails with { type: 'div' }
? In other words, React.isValidElement
should always be true
in order for this validator to pass.
var ACCEPTABLE_TYPES_OF_EXPECTED_TYPES = ['string', 'function']; | ||
|
||
if (ACCEPTABLE_TYPES_OF_EXPECTED_TYPES.indexOf(typeof expectedType) === -1) { | ||
process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to ElementWithType, expected an Html tag name or a Component.') : void 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should not use warning
here; I'm suggesting this have a literal throw
statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would be different from the behaviors of other type checkers.
https://github.com/congwenma/prop-types/blob/add-componentOfType/factoryWithTypeCheckers.js#L277
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, that seems like a missed opportunity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't this be a useful pattern by not making a big deal
about prop types in production?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean; invalid props are bugs. The point of not warning about them in production is performance; the exception I'm hoping for here would only apply to dev anyways, since the entire propType validator is compiled out anyways in production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry I thought you mean replacing the entire line with a throw
.
I think what you are suggesting can make things cleaner and easier, plus we'd be removing dependency on fbjs/warning
, however I think theres some logic in fbjs/warning
that helps debugging prop-types and handle some special cases, and this probably warrants a separate PR.
@congwenma would you mind rebasing this, and addressing outstanding comments? |
@congwenma #146 (comment) in particular |
} | ||
|
||
function validate(props, propName, componentName, location, propFullName) { | ||
var propValues = [].concat(props[propName]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should just be props[propName]
; there's no reason to support multiple values here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying the support of multiple element types should be using oneOf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oneOfType, yes.
Co-Authored-By: congwenma <congwen.ma@gmail.com>
Co-Authored-By: congwenma <congwen.ma@gmail.com>
Co-Authored-By: congwenma <congwen.ma@gmail.com>
Co-Authored-By: congwenma <congwen.ma@gmail.com>
@@ -51,6 +51,7 @@ module.exports = function() { | |||
objectOf: getShim, | |||
oneOf: getShim, | |||
oneOfType: getShim, | |||
elementWithType: getShim, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also let’s name this elementType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elementType already exist, looks like this PR beated us to it. b67bbd4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, indeed - looks like #211 may have replaced this.
Replaced with #211. Thanks for the contribution! |
Adds
ComponentOfType
propType checker.This helps check Component's type on the receiving end.