はじめに
今更ですが、みなさんReactコンポーネントを作る際に「なんで、JSXが複数行になる場合にのみ()で囲まないといけないのか?」と疑問に思ったことはないでしょうか?
僕は夜も眠れないくらい気になったので、ちょっと調べてみました。
↓こんな場合の()です!
import React from 'react';
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
結論
最初に結論からいうと、ReactでJSXが複数行になる場合には()で囲んだ方が良いです!
主な理由
- 可読性向上のため
- フォーマットを揃えるため
これだけだとまだ眠れないと思うので、調査した内容をまとめます。
まず、あの()は何であるか
グループ化演算子の()です。
みなさんもよく(1 + (2 * 3))
などで利用する評価の優先順位を制御する演算子ですね!
ちょっと形式が変わるだけで人間すぐに混乱してしまいます。
この()で囲うことで、複数行のJSXも1つの式(Expression)として解釈されるようにしているんですね!
参考: MDN グループ化演算子
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Grouping
React公式ドキュメントの見解
読みやすさのため JSX を複数行に分けています。必須ではありませんが、複数行に分割する場合には、自動セミコロン挿入の落とし穴にはまらないように括弧で囲むことをおすすめします
可読性の向上と自動で文末にコロンが挿入されるのを防ぐために括弧で囲むのをオススメしてます。
参考:JSX の導入
https://ja.reactjs.org/docs/introducing-jsx.html
実際に()で囲わないとどうなるのか試してみる
では、実際に()で囲わないとどうなるのか試してみましょう。
今回は、下記のReact公式からリンクされているCodepenのコードを利用して色々試してみました。
参考:CodePen
https://ja.reactjs.org/redirect-to-codepen/components-and-props/rendering-a-component
例1: JSXを変数宣言時に代入
var hello =
<div>
<h1>Hello</h1>
</div>;
const element = <Hello name="Sara" />;
ReactDOM.render(element, document.getElementById('root'));
=> 問題なく動作する。
例2: JSXをアロー関数でリターン
const Hello = (props) =>
<div>
<h1> Hello, {props.name} </h1>
</div>
const element = <Hello name="Sara" />;
ReactDOM.render(element, document.getElementById('root'));
=> 問題なく動作する。
例3(OKパターン): JSXをfunction内でリターン
function Hello(props) {
return <div>
<h1> Hello, {props.name} </h1>
</div>
}
const element = <Hello name="Sara" />;
ReactDOM.render(element, document.getElementById('root'));
=> 問題なく動作する。
ただし、下記のようにreturnで改行された場合は当然ですが、returnで関数が終了してしまうので動作しません。
例3(NGパターン): JSXをfunction内でリターン
function Hello(props) {
return
<div>
<h1> Hello, {props.name} </h1>
</div>
}
const element = <Hello name="Sara" />;
ReactDOM.render(element, document.getElementById('root'));
このようにみていくとreturn文が登場するような
スタイルガイドではどうなっているか?
JavaScript Standard Styleでの推奨の書き方
JavaScript Standard Style で推奨の記載は下記です。
推奨以外の書き方以外はerrorになるようにeslintrc.json
で定義されています。
"react/jsx-wrap-multilines": ["error", {
"declaration": "parens-new-line",
"assignment": "parens-new-line",
"return": "parens-new-line",
"arrow": "parens-new-line",
"condition": "parens-new-line",
"logical": "ignore",
"prop": "ignore"
}]
変数宣言時に代入
var hello = (
<div>
<p>Hello</p>
</div>
);
JSXをアロー関数でリターン
var hello = () => (
<div>
<p>World</p>
</div>
);
JSXをfunction内でリターン
function hello() {
return (
<div>
<p>Hello</p>
</div>
);
}
参考:
JavaScript Standard Styleでの方針
- https://github.com/standard/standard/issues/710
- https://github.com/standard/standard/commit/ccaf4390d9ae0829fdd31b2d69df143e9138e77d
EsLint React Pluginでの推奨の書き方
EsLint React PluginでもJSXが複数行になる場合には()で囲もうという方針ですね。
ただEsLint React Pluginではデフォルトでの設定がparens
となっている点が異なります。(JavaScript Standard Style では parens-new-line
となっています。)
Prevent missing parentheses around multiline JSX (react/jsx-wrap-multilines)
Wrapping multiline JSX in parentheses can improve readability and/or convenience.
参考:jsx-wrap-multilines.md
https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-wrap-multilines.md
デフォルト設定
{
"declaration": "parens",
"assignment": "parens",
"return": "parens",
"arrow": "parens",
"condition": "ignore",
"logical": "ignore",
"prop": "ignore"
}
parens
とparens-new-line
の違い
どちらも()で囲おうというのは同じなのですが、parens-new-line
の方が少し厳しいです。
どちらもOK
var hello = (
<div>
<p>Hello</p>
</div>
);
どちらもNG
var hello = <div>
<p>Hello</p>
</div>;
parens
ではOKだが、parens-new-line
でNG
var hello = (<div>
<p>Hello</p>
</div>);
最後に
ReactでJSXが複数行になる場合には()をつけましょう!
夜、()に悩まずに眠れるようになった人が少しでも増えたなら、幸いです。