Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override/extend static properties on ES7 classes in React.js

ES7 introduces the concept of static property and method definitions. Along with an ES7-capable transpiler, these can be used in React to specify validators and defaults for props, like so:

export default class ComponentOne extends React.Component {
    static propTypes = {
        foo: React.PropTypes.string
    }
    static defaultProps = {
        foo: 'bar'
    }
    // ...
}

This is super handy, but gets tricky when subclasses come into play. For example, say the following module is added to the same codebase as ComponentOne above:

export default class ComponentTwo extends ComponentOne {
    static propTypes = {
        baz: React.PropTypes.number
    }
    static defaultProps = {
        baz: 42
    }
    // ...
}

I'd like ComponentTwo to "inherit" the property validators and defaults of its superclass, ComponentOne. Instead, propTypes and defaultProps on ComponentTwo shadow those on ComponentOne, and React tosses out those defined on ComponentOne.

Since super is a reference to the current class's prototype, and static is supposed to reference values hung directly off the prototype, I thought this might work:

import _ from 'lodash';
export default class ComponentTwo extends ComponentOne {
    static propTypes = _.merge(super.propTypes, {
        baz: React.PropTypes.number
    });
}

However, this generates an error, presumably from Babel: Parsing error: 'super' outside of function or class.

This works, but is not very portable:

export default class ComponentTwo extends ComponentOne {
    static propTypes = Object.assign({
        baz: React.PropTypes.number
    }, ComponentOne.propTypes);
}

Are there any other ways to do this more cleanly/reusably?

like image 258
ericsoco Avatar asked Oct 23 '15 22:10

ericsoco


People also ask

Which keyword's are required to create a static property within a class?

The static keyword defines a static method or property for a class, or a class static initialization block (see the link for more information about this usage).

Are static properties inherited?

Static properties and methods are inherited. For class B extends A the prototype of the class B itself points to A : B.

What is a static property in React?

TL;DR: Static properties are properties of a class, not of an instance of a class.

Are static methods inherited JavaScript?

A static method in JavaScript is a method that has a static keyword prepended to itself. Such methods cannot be accessed through instantiated objects but could be accessed through the class name. This is because static methods belong to the class directly. Inheritance even applies to static methods.


1 Answers

I stumbled upon this question, and it's been almost 3 years, but who know, someone might need it. (And it's still relevant)

Given that when you extend a class it automatically inherits of its parent class, you would not need to overwrite the static propTypes property.

Given a parent class:

class Parent {
  static propTypes = {
    parentProp: PropTypes.string
  }
}

If you don't want to add other propTypes/defaultProps, you can simply:

class Children extends Parent {
  // Do not declare the propTypes, it will extends by itself.
}
console.log(Children.propTypes); // Will output an object with parentProp in it

If you want to explicitly tell that you extends Parent propTypes, or add new propTypes:

class Children extends Parent {
  static propTypes = {
    ...Parent.propTypes, // Yes, you can spread static properties like everything else
    childProp: Proptypes.number,
  }
}

Small note, for this to work properly with Babel, you might need to include the transform-es2015-classes babel plugin in your plugins or preset. My .babelrc:

"presets": [
  ["env", {
    "include": ["transform-es2015-classes"]
  }],
  "stage-0",
  "react"
],

Hope this helps!

like image 79
ChrisR Avatar answered Oct 13 '22 06:10

ChrisR