2
1

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 1 year has passed since last update.

ReactAdvent Calendar 2022

Day 18

eslint-plugin-functionalを使ってReactでのイミュータブルを強制する

Last updated at Posted at 2022-12-17

目次

  • Reactで変数がイミュータブルであることがなぜ重要か
  • eslint-plugin-functionalを使ってイミュータブルを強制する

Reactで変数がイミュータブルであることがなぜ重要か

※ そんなのもう知ってるよ!って方はスキップしてください。

そもそもイミュータブルとは?

こちらの記事が分かりやすいので参考にしていただければ

Reactにおけるイミュータブルの重要性

一般にイミュータブルだと一度定義した変数が不変なため、コードの挙動が予測可能というメリットがある。

さらに、Reactにおけるイミュータブルであることのメリットは状態(変数)を更新したにもかかわらず、Reactがそれを検知できず、画面に更新が反映されないというバグ?を防ぐことができることできること。

ミュータブルな変更をおこなった場合にどうなるか

Reactのコンポーネントはstateまたはpropsが更新されたら、更新を検知し再レンダーするが、"更新された"の判断はimmutableな変更を前提にしている。つまり、メモリの参照先を比較している。なので、オブジェクト型のstateやpropsをmutableに変更した場合、メモリの参照先は変更前後で同じなため、reactは変更を検知できない。

stateやpropsをミュータブルに変更した場合、再レンダーされないだけで、値としては更新されているので、別のトリガーで再レンダーが起こったときに、隠れていたの差分が現れて、バグっぽく動いてしまう。

↓mutable changeを押した差分が、immutable changeをした際に現れる。
https://codesandbox.io/s/react-typescript-forked-fd5r40?file=/src/App.tsx
タイトルなし.gif

上の例ではコンポーネントの自身のstateの更新の例を挙げたが、constで定義されるような通常の変数も、コンポーネント内で使用している他のコンポーネントのpropsに渡した場合に同じことが起こるため、変数もimmutableであるべき。

上記のような理由から、特にReactでは変数全般はイミュータブルであることが重要。

イミュータブルにするにはどうしたらいいか?

Typescriptでオブジェクト型の変数をイミュータブルにするにはreadonlyをつければOK。参考

ただ、、、
開発中に毎回readonlyをつけるのは面倒だし、つけ忘れがあるかもしれない、、、

そこで、eslintにeslint-plugin-functionalというimmutableを強制してくれる設定があるので使おう、というお話!

eslint-plugin-functionalを使ってイミュータブルを強制する

設定方法

基本的に公式のgithubを見ながらeslintを設定すれば良い。

eslint-plugin-functionalは

An ESLint plugin to disable mutation and promote functional programming in JavaScript and TypeScript.

とあるように、名前の通りjs, tsの関数型プログラミングをサポートするもので、イミュータブルを強制する以外にも、さまざまな設定ができる。

設定と適用されるルールの対応は、表になっている。

例えば、 no mutationsのルールの場合

設定は以下の3種類があり、
🙈: plugin:functional/no-mutations
🙉: plugin:functional/lite
🙊: plugin:functional/recommended

それぞれの設定の際に適用されるルールは✅が表で付いている項目になる。
※↓の通り、no mutationsの場合はどの設定にしても全てのルールが適用される。
noMutation

ミュータブルな変更をさせないだけであれば以下の設定でOK。

{
  ...
  "plugins": [
    ...
    "functional"
  ],
  "extends": [
    ...
    "plugin:functional/no-mutations",
  ]
}

プラスアルファでより関数型の要素を取り入れたいのならliterecommendedを設定すると良い。

個人的にはliteにして、no-return-voidなど、どうしてもないと不便なもののみ個別にoffにするのが良さげ。

その他設定しておいた方がいいこと

  • vscodeのeslint拡張機能をいれ、保存時のeslint自動修正
    readonlyを自分で毎回書かなくて良い。

  • 自動テストでのeslintもチェック
    仕組みとしてイミュータブルであることを保証できる。レビューアとしてもイミュータブルになっていることが保証されているので、レビュー観点の削減にもなる。

2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?