🐶

JSXで予期せぬ動作を防ぐための eslint-plugin-jsx-expressions の紹介

2022/09/25に公開

はじめに

皆さんはJSXにてこういった条件分岐をしているコードを見た覚えはないでしょうか?
かくいう私は何度か書いた覚えが(レビューした覚えも)あります。

type Props = {
  count: number;
};

const Container = ({ count }: Props) => {
  return (
    <div>
      {count && <Counter />}
    </div>
  );
};

しかし上記のコードは開発者の予期せぬ不具合を含んでいます。
count0 だった場合、0 がレンダーされてしまいます。(React公式ドキュメントにも記載されています)

zero

Webの場合アプリが使えなくなるような大きなバグには繋がりませんが、React Nativeの場合アプリがクラッシュする致命的なバグにも繋がります。
こういった特定条件でのみ発生する動作はコードや目視では発見しづらいため、何らかの方法で自動的に検知したいところです。

この記事ではこのコードを検知・修正してくれる eslint-plugin-jsx-expressions について紹介します。

https://github.com/hpersson/eslint-plugin-jsx-expressions

なぜ発生するのか

そもそもこの現象はなぜ発生するのでしょうか。
JSの論理積(&&),論理和(||)といった演算子は、短絡評価の結果の値が falsy だった場合その falsy の値をそのまま返します。(論理和(||)の場合 truthy の値)

論理積 (&&) - JavaScript | MDN
論理和 (||) - JavaScript | MDN

すなわち count && <Counter /> のような条件で count0 だった場合、以下のようなコードとして解釈されます。

const Container = () => {
  return (
    <div>
      0
    </div>
  );
};

この現象を回避するためには論理積の左側の判定に boolean を使用する必要があります。

const Container = ({ count }) => {
  return (
    <div>
      {!!count && <Counter />}
    </div>
  );
};

しかし、人間の注意力には限界があるので(面倒なので)ESLintで自動検知・修正をしたいところです。

eslint-plugin-jsx-expressionsの導入

このコードを検知できる eslint-plugin-jsx-expressions を導入します。
導入方法はREADMEを参照してください。

https://github.com/hpersson/eslint-plugin-jsx-expressions

導入してエラーが発生した箇所を自動修正すると、booleanではない値を自動的にbooleanに変換するように修正してくれます。

type Props = {
  count: number;
};

const Container: FC<Props> = ({ count }: Props) => {
  return (
    <div>
      {!!count && <Counter />}
    </div>
  );
};

以上です。
有用なESLint Pluginを開発してくださった作者様に感謝を!

まとめ

  • JSX内にて論理積で条件を記述すると予期せぬ不具合が起きうる
  • eslint-plugin-jsx-expressionsを導入すると防げる
GitHubで編集を提案

Discussion