ESLintを活用して、Airbnb Styleの記述方法を学ぶ。

Tatsuya Asami
11 min readNov 13, 2018

--

【所要時間】

6時間13分(2018年11月12, 13日)

【概要】

  • ESLintによるわからない警告を放置していたので解決する。

【要約・学んだこと】

Create-React-Appから作成したこちらのアプリhttps://link.medium.com/3yNvScMsMR

の記述をAirbnbの記述方法に従い修正する。

現状各ファイルに一番上に記述されている

import React from 'react;

の記述に対して

”error Parsing error: The keyword ‘import’ is reserved”

というエラーが出ている。

製作時に設定を色々変えて見たりしてよくわからない状態になっているので、一度ESLintをuninstallし、eslint-config-airbnb をインストールし直す。

ここでeslintもインストールすると、npm startでローカルに立ち上げる際にバージョン相違でエラーとなってしまうので注意。

./node_modules/.bin/eslint --init

とりあえずnpm runでlocal hostは立ち上がり、importのエラーも消えた。

準備はできたので、警告が出ている記述方法を見直し、警告を消していく。

リンク先に飛ぶとESLintの該当する記述方法の説明のページに飛べるのでありがたい。
airbnb JavaScript styleはここに書いてある。

//airbnb JavaScript styleではないconst mapDispatchToProps = dispatch => {
return {
addInfo: info => dispatch(addInfo(info)),
};
};
//aribnb JavaScript styleconst mapDispatchToProps = dispatch => ({
addInfo: info => dispatch(addInfo(info)),
});

上記のように直すと、警告は消えた。

慣れないが規則なので、警告が出たら従うようにすればいいのかと思う。
これで複数人で作業していても、一貫した記述方法になるはずである。

引き続き直していく。

NG
const target = event.target;
const name = target.name
OK
const { target } = event;
const { name } = target;

inputをlabelで囲んでいない。

NG
<label>
Name
</label>
<br />
<input
type="text"
name="name"
value={name}
onChange={this.handleChange}
/>
OK
<label htmlFor="name">
Name
<br />
<input
type="text"
name="name"
id="name"
value={name}
onChange={this.handleChange}
/>
</label>

buttonのtypeを指定していない。

NG
<button onClick={this.handleClear}>
Reset
</button>
OK
<button type="button" onClick={this.handleClear}>
Reset
</button>

array, any, Object等はより細かくtypeを指定できるため使えない。

NG
ConnectedDataBase.propTypes = {
columns: PropTypes.array.isRequired,
};
OK
ConnectedDataBase.propTypes = {
columns: PropTypes.arrayOf(PropTypes.string).isRequired,
};

indexをkey(listやtableの)に割り当ててはいけない。

NG
{info.map((state, index) => (
<tr key={`tr${index}`}>
)
OK
{info.map(state => (
<tr key={`tr${state.id}`}>
))}

if 分でreturnを返す場合、returnの後のelseはいらない。(違和感がすごいあるが・・・)

NG
if (selectedGender !== 'all') {
return value.gender === selectedGender;
} else {
return value.gender

OK
if (selectedGender !== 'all') {
return value.gender === selectedGender;
}
return value.gender;

等を修正した。

また、最後のkeyの修正にidを指定したため、Reduxのinfo配列の各オブジェクトに、idというプロパティも追加した。

情報入力のページから新たにデータが追加された際にもidをdispatchする必要があるので、そちらも修正した。

// Form.js...handleSubmit(event) {
...
age = parseInt(age, 10);
arrival = parseInt(arrival, 10);
leave = parseInt(leave, 10);
const id = uuidv1();
this.props.addInfo({ //
id, name, age, gender, department, position, arrival, leave, location,
});
  • 警告を強制的に消す
    裏技ではないが、強制的に警告を消したい部分では “eslint-disable-line”で消せる。
    今回は下記のような場合は消していいと思われる。

age, arrival, leaveのvariableは、stringsではなくnumberで送信したいので、parseIntを使っている。この3つだけをlet, 他をconstで記述するよりは、eslintの警告を消した方がスマートなように思われる。

ファイル全体で特定のルールを無効にしたい場合には下記のように書けばよい。

/* eslint label-has-associated-control, label-has-for: 0 */
  • JSXタグ部分のESlintを無効にする。
<label htmlFor="location"> {// eslint-disable-line
}

このように書く。

  • alertは原則使わない。

alert, confirm, prompt functionはdebugコードで使われるため、使うべきではない。また、UI要素として目立つので、他の適切なものに置き換えるべきとも考えられる。

https://eslint.org/docs/2.0.0/rules/no-alert

今回はalertをやめて、背景と文字色を赤にして警告することにした。
stateに新たにnameEmpty, nameAlertColor, wrongArrival, arrivalAlertColorという4つの空白の初期stateを持たせ、setStateすると警告メッセージと色を変えることにした。

if (name === '') {
this.setState({
nameEmpty: 'Put in your Name',
nameAlertColor: 'red',
wrongArrival: '',
arrivalAlertColor: '',
});

} else if (arrival > leave) {
this.setState({
wrongArrival: 'Should be earlier than Leaving',
arrivalAlertColor: 'red',
nameEmpty: '',
nameAlertColor: '',
});
<label htmlFor="name" style={{ backgroundColor: nameAlertColor }}>
Name
<br />
{nameEmpty}
<input
type="text"
name="name"
id="name"
value={name}
onChange={this.handleChange}
style={{ backgroundColor: nameAlertColor }}
/>
</label>

見た目はよくないが、利用者としてはどこに問題があるかわかりやすい。

これで赤線と赤丸だらけだったATOMの画面から警告が全て消えた。
console画面でも警告は出ていない。

【わからなかったこと】

  • formでlabelタグを使う際に、inputの場合は問題なく警告が消えたが、selectの場合警告が消えない。色々調べたがどう記述すればいいのかわからなかった。

https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md

<label htmlFor="gender">
Gender
<br />
<select
id="gender"
name="gender"
onChange={this.handleChange}
value={gender}
>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Others">Others</option>
</select>
</label>
<br />
  • 親要素を変更するsubmitHandlerの記述方法がわからない。
this.props.addInfo({
name, age, gender, department, position, arrival, leave, location,
});

一番最初に修正したように const addInfo = this.props.addInfo とすると、addInfoという変数名はすでに使われているという別の警告が出てしまう。

【感想】

このコードを書いている際は、記述方法などを調べながらやると膨大な時間がかかりそうだったので、わからない点は全て無視したが正解だった。(5時間以上かかった。)

Airbnb styleの記述方法を理解すると同時に、知らなかった記述法を知ったことで、stackoverflowやチュートリアルなどで出会うよくわからない記述方法が少しは減ったはず。

また、eslintやuuidをインストールした際に色々おかしくなったが、以前の経験から、

→それっぽいことをやってみる
→create-react-appで新しいプロジェクトを作り、インストールしてうまく起動することを確認する
→インストールしたものをアンインストール
→node_modules, package-lock.json, yarn.lockを削除
→再度インストール

という判断をするまでの時間が早くなったので、本題と違う部分でのタイムロスが減らせた。

--

--

Tatsuya Asami
Tatsuya Asami

Written by Tatsuya Asami

Front end engineer. React, TypeScript, Three.js

No responses yet