Is it OK to put propTypes and defaultProps as static props inside React class?
Asked Answered
C

4

41

This is the way I've been doing it for quite some time now:

export default class AttachmentCreator extends Component {
  render() {
    return <div>
      <RaisedButton primary label="Add Attachment" />
    </div>
  }
}

AttachmentCreator.propTypes = {
  id: PropTypes.string,
};

But I've seen people doing it this way:

export default class AttachmentCreator extends Component {
  static propTypes = {
    id: PropTypes.string,
  };

  render() {
    return <div>
      <RaisedButton primary label="Add Attachment" />
    </div>
  }
}

And in fact I've seen people setting initial state outside the constructor as well. Is this good practice? It's been bugging me, but I remember a discussion somewhere where someone said that setting default props as a static is not a good idea - I just don't remember why.

Curtilage answered 21/4, 2016 at 18:59 Comment(2)
You've asked about static getters, but your example is a static class property, are you wondering about both?Mccandless
Sorry, static class property. I'll editCurtilage
P
14

non-function properties are not currently supported for es2015 classes. its a proposal for es2016. the second method is considerably more convenient, but a plugin would be required to support the syntax (theres a very common babel plugin for it).

On the other end, a hand full of open source projects are beginning to treat proptypes like TypeScript interfaces, or ActionConstants and actually create separate folders/files that house various component prop types and are then imported into the component.

So in summary, both syntaxes are ok to use. but if you want to only use strictly ES2015, the latter syntax is not yet supported in the specification.

Psychosomatic answered 21/4, 2016 at 21:6 Comment(0)
L
43

In fact, it's exactly the same in terms of performance. React.JS is a relatively new technology, so it's not clear yet what are considered good practices or don't. If you want to trust someone, check this AirBNB's styleguide:

https://github.com/airbnb/javascript/tree/master/react#ordering

import React, { PropTypes } from 'react';

const propTypes = {
  id: PropTypes.number.isRequired,
  url: PropTypes.string.isRequired,
  text: PropTypes.string,
};

const defaultProps = {
  text: 'Hello World',
};

class Link extends React.Component {
  static methodsAreOk() {
    return true;
  }

  render() {
    return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>
  }
}

Link.propTypes = propTypes;
Link.defaultProps = defaultProps;

export default Link;

They are declaring a const with the propTypes object literals, keep the class pretty clean and assign them later to the static properties. I personally like this approach :)

Lid answered 21/4, 2016 at 19:36 Comment(4)
After using the experimental feature, I think I much prefer to err on the side of a more stable proposal. Airbnb's styling has never misguided me.Selangor
Sorry , but what is the point to separate the propTypes declaration? - what are the advantages?Folie
In my example, there's really no advantage, it's just an opinionated way of declaring things. But it can be useful in scenarios where you may want to reuse data structures across components and you don't want to repeat propTypes declarations in each one :)Lid
In 2020, w/ React 16+ and spread syntax available in the target environments (or polyfilled), Component.propTypes = { some: 'val', ...Related.propTypes, nestedChildProps: { ...NestedChild.propTypes }, override: 'val' } and the entire kitchen sink all do exactly what you'd expect at runtime. Linters have gotten good, but that's where you'll have to accept a trade-off, even today.Uhlan
P
17

Oh yes, it's totaly legit with Babel (or other transpilers)

class DataLoader extends React.Component {
  static propTypes = {
    onFinishedLoading: PropTypes.func
  }

  static defaultProps = {
    onFinishedLoading: () => {}
  }
}

...as it gets transpiled to this anyway.

class DataLoader extends React.Component {}

DataLoader.propTypes = {
  onFinishedLoading: PropTypes.func
};

DataLoader.defaultProps = {
  onFinishedLoading: () => {}
};

Static fields get transpiled as properties on the class object under the hood. Look here at Babel REPL.

Moreover, assigning state or other class fields directly in the class body gets transpiled into the constructor.

Pubilis answered 18/4, 2018 at 11:13 Comment(0)
P
14

non-function properties are not currently supported for es2015 classes. its a proposal for es2016. the second method is considerably more convenient, but a plugin would be required to support the syntax (theres a very common babel plugin for it).

On the other end, a hand full of open source projects are beginning to treat proptypes like TypeScript interfaces, or ActionConstants and actually create separate folders/files that house various component prop types and are then imported into the component.

So in summary, both syntaxes are ok to use. but if you want to only use strictly ES2015, the latter syntax is not yet supported in the specification.

Psychosomatic answered 21/4, 2016 at 21:6 Comment(0)
P
0

If the component is state-less, meaning it does not change it's own state at all, you should declare it as a stateless component (export default function MyComponent(props)) and declare the propTypes outside.

Whether it's good practice to put initial state declaration in constructor is up to you. In our project we declare initial state in componentWillMount() just because we do not like the super(props) boilerplate you have to use with the constructor.

Pedroza answered 21/4, 2016 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.