Thom Smith
Thom Smith

Reputation: 14086

How can I tell if a function is a class?

I'm writing a React component that takes a renderer property. In general, this is a function that takes in an object of arguments and returns another React component. However, I would like for users of my component to be able to pass in a React component class instead. I would then internally wrap that class in a function:

class MyComponent extends React.Component {
    render() {
        const { renderer } = this.props;

        const renderFn = (renderer.isAComponentClass())
            ? (props => <renderer {...props} />)
            : renderer;

        return <div>{ renderFn(someArgs) }</div>;
    }
}

Of course, in JavaScript, a class is also a function. How can I check whether renderer is a class? I am using Babel 6.

I am aware that I could simple return <renderer {...someArgs} />. I would rather not do this if I can avoid it, because this unnecessarily bloats the component tree.

Upvotes: 2

Views: 73

Answers (1)

Estus Flask
Estus Flask

Reputation: 222498

It is possible to detect native classes with regular expression - as long as they don't implement toString method that will change their representation as a string.

It is not possible to detect if a function is a class due to the fact that classes don't differ from functions in transpiled code. This is a good reason to not even try to distinguish them programmatically.

It is possible to check if React.Component is the ancestor of a function/class with

renderer.prototype instanceof React.Component

Since this puts unnecessary restriction, a better option is to duck test it, like

renderer.prototype && ['render', 'setState', ...]
  .map(methodName => typeof renderer.prototype[methodName])
  .every(methodType => methodType === 'function')

However, none of these checks are accurate. prototype property can be messed up in some cases, e.g. when a class is decorated. The only way to certainly know that a class is a component is to instantiate it first.

And API would be cleaner if renderer function and component could never be confused, for instance separate renderer and rendererComponent properties.

Upvotes: 1

Related Questions