2
votes

I am creating a component that I want the element type to be configurable.

const Col = ({ containerElement, children }) => {
  return (
    <containerElement>
      {children}
    </containerElement>
  );
};

Col.defaultProps = {
  containerElement: 'div'
};

So container element could either be as in the defaultProps above or it could be a component.

<Col containerElement={<MyComponent} />

I can't get the propTypes to validate, I have tried this:

Col.propTypes = {
  className: PropTypes.string,
  containerElement: PropTypes.oneOf([
    PropTypes.string,
    PropTypes.element
  ]),

But it does not validate correctly.

Warning: Failed propType: Invalid prop componentClass of value div supplied to Col,

3
What exactly are you passing to the component? If the value is really an element, then you cannot use it as <containerElement> anyway. <containerElement> is syntactic sugar for React.createElement('containerElement', ...). Even if it is a string, 'containerElement' will be passed to React.createElement, not the variable containerElement. Before worrying about the validation error I would make sure the code itself produces the correct result (i.e. works correctly). - Felix Kling
Agree with @FelixKling. You'll want to instantiate the <Element> via something like const ContainerElement = containerElement.inner. See this question: stackoverflow.com/a/39655113/504018 - patcon

3 Answers

3
votes

Now with prop-types 15.7.0 released you can do:

Col.propTypes = {
  ...
  containerElement: PropTypes.elementType,
}
1
votes

You don't have componentClass property defined on your component - your prop is called containerElement and you should use oneOfType:

Col.propTypes = {
  className: PropTypes.string,
  containerElement: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.element
  ])
1
votes

Try this:

Col.propTypes = {
    className: PropTypes.string,
    containerElement: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
}

because React components are functions in a global sense, and

typeof (class MyClass {}) // => "function"