背景
TypeScript + React + Viteでウェブアプリを作っているのですが、管理クラスのようなものが必要になりました。
class Application { readonly version: string private _theme: 'dark' | 'light'
get theme(): 'dark' | 'light' { return this._theme }
changeTheme = () => { this._theme = this._theme === 'dark' ? 'light' : 'dark' }}上は大雑把な感じですが、こういうのを作ったときにApplicationのクラスの何かの要素が変化したときにコンポーネントの再レンダリングをして欲しいわけです。
ところがクラスは参照渡ししかしない上にクラスのプロパティが変化してもReactはクラスのインスタンスが変化したとは検知してくれません。
よって、これはchangeThemeを呼び出してthis._themeを変更してもApplicationクラスのインスタンスが変わったと認識してくれないので表示は全く変わりません。
これが困るのでなんとかしたいというわけですね。
SwiftUIの場合
SwiftUIもReactと同じように宣言型のフレームワークなので同様の問題がありました。
| フレームワーク | 状態管理 | クラス管理 |
|---|---|---|
| SwiftUI | @State | @Observable |
| React | useState | - |
| Jotai | atom | - |
ところがSwiftUIの場合にはクラス自体に@Observableを宣言して、プロパティの変化をチェックしたい場合に@Publishedをつけることでクラスのプロパティが変化したことをSwiftUIのフレームワークに通知する仕組みがありました。
ところがReactにはデフォルトでその機能はないようで、この時点で結構困ります。
ログインフォームくらいであればユーザー名とパスワードを管理すればいいだけなので@StateやuseStateで十分なのですがアプリの設定などであればたくさんのプロパティが必要なので、それらを必要とするコンポーネントで何回も呼び出していると流石にめんどくさいです。
また、クラスの場合にはプロパティAとプロパティBが密結合になっている場合があるので、別のStateで管理すると表示上の非同期を招きかねません。
SwiftUIの場合にはより単純なクラスの状態管理として
@Observationもあったりします
@Observableの欠点
じゃあSwiftUIの@Observableは便利なのかというとそうではない一面もあります。
というのも、クラス自体を@Observableとして宣言しないといけないので、外部のライブラリが使っているクラスはラッパーを作るなり拡張クラスを作らないとObservableに対応させることができません。この時点で結構めんどくさいです。
まあSwiftUIの愚痴はどうでもいいです、ぶっちゃけそんなに困っていません。困っているのはReactです。