onChange地獄からの脱出:Knockout.jsのdata-bindをReactで活用する
onChange地獄からの脱出:Knockout.jsのdata-bindをReactで活用する
はじめに
Reactを使ってフォームを作るとき、onChange
による状態更新が必須です。
<input value={value} onChange={e => setValue(e.target.value)} />
これはReactの「制御されたコンポーネント」という設計によるものですが、地味に面倒です。
実はKnockout.jsのdata-bind
とreact-koを使えば、ReactのフォームでもonChangeを書かずに済む方法があります。
本記事では、
- なぜReactはonChangeが必要なのか?
- それをKOのバインディングでどう解決できるか?
-
react-ko
を使ってどう組み合わせるのか?
という観点から、Reactユーザーの「イベント地獄」を救う実践的アプローチを紹介します。
Reactだけでフォームを作る場合の苦しみ
Reactは入力要素の状態を「コンポーネントの状態(state)」と結びつけるため、フォーム入力には onChange
を毎回書く必要があります。
const [name, setName] = useState('')
<input value={name} onChange={e => setName(e.target.value)} />
シンプルなフォームでも、入力項目が多くなると useState
と onChange
の量が激増します。
data-bind
ならonChangeは不要
KOのKnockoutでは、observableを定義して data-bind="value: name"
を使えば、
入力要素とデータが自動で同期されます。
<input data-bind="value: name" />
これだけで双方向バインディングが成立します。
Reactから見ると「なんでonChangeなくていいの!?」という不思議な体験ですが、KOはそれを昔からやっていました。
解決策:react-koでKOのバインディングをReactに持ち込む
react-ko
を使えば、Reactコンポーネントの中で data-bind
を記述できるようになります。
つまり、ReactのJSX内でKOのフォームバインディングが使えるということです。
インストール方法
npm install react-ko knockout
使用例:KO observableでReactフォームを構築
import ko from 'knockout'
import { KnockoutScope } from 'react-ko'
export function KoInput({ value }) {
const vm = { value }
return (
<KnockoutScope viewModel={vm}>
<input data-bind="value: value" />
</KnockoutScope>
)
}
// 使用例
const viewModel = {
name: ko.observable('Alice')
}
<KnockoutScope viewModel={viewModel}>
<KoInput value={viewModel.name} />
</KnockoutScope>
このように、useState
も onChange
も不要。
KOのobservableと data-bind
に任せることで、
Reactでも直感的に双方向バインディングが実現できます。
おわりに
onChangeを書きたくない。
でもReactで構築されたUIの中で、状態管理の責務は保ちたい。
そんな悩みに対して、Knockout.jsのdata-bind
という昔ながらの知恵を活かすことは、ある意味で逆転の発想かもしれません。
react-koを使えば、Reactの世界にKOのバインディングの便利さを取り入れることができます。
ReactはUIの状態を厳密に管理できる反面、フォームのような日常的なUIでも毎回イベント処理を書く必要があります。
KOの data-bind
は、そういった煩雑さを取り除く強力な手段です。
react-ko を使えば、そのKOの恩恵をReactの中で活かせます。
「onChange地獄に疲れた…」というReactユーザーは、ぜひ一度 react-ko
を試してみてください。
Discussion