14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Class Propertiesを使ったReactコンポーネントをESLintで静的検証

Last updated at Posted at 2016-03-11

ある程度Babelとか知ってる人向きです。

要約

  1. Class Property DeclarationsでReactのPropTypes指定が捗る
  2. ESLintそのままではClass Property Declarationsに対応してない
  3. babel-eslintパーサ使えば解決(ただしestraverse-fbは手動で入れろ)

以上。estraverse-fb周りはそのうち修正されそう。

Class Property DeclarationsでReactのPropTypes指定が捗る

ES.nextのClass Property Declarationsでクラスにプロパティ生やせるよう提案されている。
それを使えばReactのpropTypes指定が捗るようになる。やったぜ。

MyButton.jsx
import React from 'react';

export default class MyButton extends React.Component {
  static propTypes = {
    onClick: React.PropTypes.func.isRequired
  };

  handleClick(){
    this.props.onClick();
  }
  render(){
    return (
      <button onClick={::this.handleClick}>ClickMe!</button>
    );
  }
}

使うにはBabelのstage-2stage-1以上の指定が必要。
(イベントハンドラってbindする必要あったんだっけ…?)

ESLintそのままではClass Property Declarationsに対応してない

ESLintは2.3.0からES7に対応したらしい。
ES7(ES2016)で新たに入るのは以下の二つのみ。

  • Array.prototype.includes
  • Exponentiation Operator(**)

仕様は以下から見られる。

ES7が固まった以上、昔ES7 async/awaitなんて言ってたりしたのはもはや誤用なのだが、
Class Property Declarationsが入ると勘違いして試してコケた。
誤用については以下のリンクも参考になる。

※指摘をいただいたので上記を修正

.eslintrc
{
  "parserOptions": {
    "ecmaVersion": 7
  },
  "env": {
    "browser": true,
    "es6": true
  },
  "ecmaFeatures": {
    "classes": true,
    "jsx": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    //...
  }
}
$ eslint MyButton.jsx
/src/MyButton.jsx
  4:20  error  Parsing error: Unexpected token =

/(^o^)\

babel-eslintパーサ使えば解決

というわけで、babel-eslintを入れよう。
babelパーサならES.nextの仕様のコードでも読んでくれる。
パーサ自体がbabel用なためか、いろいろオプション抜いても平気で動く。

$ npm i -D babel-eslint
.eslintrc
{
  "parser": "babel-eslint",
  "env": {
    "browser": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    //...
  }
}

ここで、estraverse-fbが存在しないと怒られたら手動で入れる

$ npm i -D estraverse-fb

estraverse-fbは2.3.0から利用しなくなったESLintの依存モジュールらしい。
babel-eslintがESLintのためにそれを読んでるとかなんとか。
上のリンクでそのうちbabel-eslintが対応すると思うので-Dは付けてないよ、ってコメントあるけど、
めんどいので-Dつけたよ。お好みで。

ビルド環境

実際はeslint直接ぶっ叩いてるわけじゃなくてwebpackのpreLoaderとして使ってる。
現状の趣味プロジェクトのビルド環境晒しとく。多分そのうち変わる。
しかし最近のjs環境って本当にカオスですよねー
みんなHaxe使えばいいのに

webpack.config.js
const path = require('path');

module.exports = [{
  entry: {
    bundle: './src/entry.jsx'
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'eslint-loader'
      }
    ],
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.scss$/,
        loaders: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.jade$/,
        loader: 'jade-react-loader'
      }
    ]
  }
}];
.eslintrc
{
  "parser": "babel-eslint",
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended"
  ],
  "env": {
    "browser": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "indent": [
      "error",
      2
    ],
    "quotes": [
      "error",
      "single"
    ],
    "linebreak-style": [
      "error",
      "unix"
    ],
    "semi": "error",
    "no-unused-vars": "warn",
    "no-console": "warn"
  }
}
.babelrc
{
  "presets": ["es2015", "stage-0", "react"]
}
14
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?