10

I'm using the airbnb eslint settings, which have a rule that enforces stateless react components to be rewritten as a pure function. The following component triggers this rule, which means that the component below would be better written as a pure function:

import React from 'react';
import { observer } from 'mobx-react';
import cssmodules from 'react-css-modules';

import styles from './index.css';
import Select from '../Select/';
import List from '../List/';

@cssmodules(styles)
@observer
export default class Analysis extends React.Component {
  render() {
    return (
      <div styleName="wrapper">
        <div styleName="column">
          <Select store={this.props.store} />
        </div>
        <div styleName="column">
          <List store={this.props.store} />
        </div>
      </div>
    );
  }
}

Analysis.propTypes = {
  store: React.PropTypes.object.isRequired,
};

However, when I rewrite it as a pure function (see below), I get the error that Leading decorators must be attached to a class declaration:

import React from 'react';
import { observer } from 'mobx-react';
import cssmodules from 'react-css-modules';

import styles from './index.css';
import Select from '../Select/';
import List from '../List/';

@cssmodules(styles)
@observer
function Analysis(props) {
  return (
    <div styleName="wrapper">
      <div styleName="column">
        <Select store={props.store} />
      </div>
      <div styleName="column">
        <List store={props.store} />
      </div>
    </div>
  );
}

Analysis.propTypes = {
  store: React.PropTypes.object.isRequired,
};

So can I write it as a pure component and still attach the decorators? Or is this a mistake in the airbnb linting rules and is it impossible to satisfy both rules?

1 Answers1

21

Ok, so the problem is the es7 style decorators. Desugaring them solves the problem:

import React from 'react';
import { observer } from 'mobx-react';
import cssmodules from 'react-css-modules';

import styles from './index.css';
import Select from '../Select/';
import List from '../List/';

function Analysis(props) {
  return (
    <div styleName="wrapper">
      <div styleName="column">
        <Select store={props.store} />
      </div>
      <div styleName="column">
        <List store={props.store} />
      </div>
    </div>
  );
}

Analysis.propTypes = {
  store: React.PropTypes.object.isRequired,
};

export default cssmodules(observer(Analysis), styles);

It's not pretty, but it does work and it doesn't trigger any errors.

  • 3
    This is correct, the decorators proposal doesn't have a concept of function decorators, only class and property decorators. So this is indeed the idiomatic way to decorator function components (it works for classes as well btw) – mweststrate Sep 18 '16 at 06:33
  • 3
    Do you know why this choice has been made? It looks odd to be able to annotate class and methods but not functions. – cglacet Feb 21 '19 at 01:09