How can I validate that the supplied prop is a component class (not instance)?
e.g.
export default class TimelineWithPicker extends React.PureComponent {
static propTypes = {
component: PropTypes.any, // <-- how can I validate that this is a component class (or stateless functional component)?
};
render() {
return (
<this.props.component {...this.props} start={this.state.start}/>
);
}
}
Using PropTypes in React PropTypes is React's internal mechanism for adding type checking to components. React components use a special property named propTypes to set up type checking.
Firstly, npm install / yarn add the prop-types package if you haven't already. Then, add your propTypes (and defaultProps too if required) after the stateless functional component has been defined, before you export it.
PropTypes is deprecated since React 15.5.
javascript - 'prop-types' should be listed in the project's dependencies, not devDependencies - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.
For anyone using PropTypes >= 15.7.0
a new PropTypes.elementType
was added in this pull request and was released on february 10, 2019.
This prop type supports all components (native components, stateless components, stateful components, forward refs React.forwardRef
, context providers/consumers).
And it throws a warning when is not any of those elements, it also throws a warning when the prop passed is an element (PropTypes.element
) and not a type.
Finally you can use it like any other prop type:
const propTypes = { component: PropTypes.elementType, requiredComponent: PropTypes.elementType.isRequired, };
EDITED: Added React's FancyButton example to codesandbox as well as a custom prop checking function that works with the new React.forwardRef
api in React 16.3. The React.forwardRef
api returns an object with a render
function. I'm using the following custom prop checker to verify this prop type. - Thanks for Ivan Samovar for noticing this need.
FancyButton: function (props, propName, componentName) {
if(!props[propName] || typeof(props[propName].render) != 'function') {
return new Error(`${propName}.render must be a function!`);
}
}
You'll want to use . Actually... PropTypes.element
PropType.func
works for both stateless functional components and class components.
I've made a sandbox to prove that this works... Figured this was needed considering I gave you erroneous information at first. Very sorry about that!
Working sandbox example!
Here is the code for the test in case link goes dead:
import React from 'react';
import { render } from 'react-dom';
import PropTypes from "prop-types";
class ClassComponent extends React.Component {
render() {
return <p>I'm a class component</p>
}
}
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
const FSComponent = () => (
<p>I'm a functional stateless component</p>
);
const Test = ({ ClassComponent, FSComponent, FancyButton }) => (
<div>
<ClassComponent />
<FSComponent />
<FancyButton />
</div>
);
Test.propTypes = {
ClassComponent: PropTypes.func.isRequired,
FSComponent: PropTypes.func.isRequired,
FancyButton: function (props, propName, componentName) {
if(!props[propName] || typeof(props[propName].render) != 'function') {
return new Error(`${propName}.render must be a function!`);
}
},
}
render(<Test
ClassComponent={ ClassComponent }
FSComponent={ FSComponent }
FancyButton={ FancyButton } />, document.getElementById('root'));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With