blog.takurinton.dev

Preact の change event

2021-09-19

こんにちは

どうも、僕です。
先日、Preact を使用して、簡単なアプリケーションのプロトコーディングをしていて、input タグのイベントハンドラを呼ぼうとしたらうまく動かくてハマりました。

以下のように定義していたのですが、結論としては、onChange ではなくて onInput を使わなければならないようです。

const HogeComponent = (): JSX.Element => {
  const onChange = ({ currentTarget }: JSX.TargetedEvent<HTMLInputElement, Event>) => {
    setValue(currentTarget.value);
  };

  // これでは動かない
  return <input type="text" value={node.value.value} onChange={onChange}></input>;

  // これで動く
  return <input type="text" value={node.value.value} onInput={onChange}></input>;
}

その差分を埋めるための preact/compat というツールも用意されていますが、今回はそれを使っていなかったのでハマってしまいました。

どうしてこうなったのか

Preact のドキュメントの Differences to React というページに記述がありました。

In Preact core, onChange is the standard DOM change event that gets fired when an element's value is committed by the user.

React onChange イベントは独自実装ではあるものの、実際にはブラウザで実行される GlobalEventHandlers.onInput と同じであり、Preact はその部分を直接使用して要素にアタッチをします。そのため、構文に差が生まれているということです。

これについてツイートをしたら、リプが飛んできました。DevRel ありがたい...。 https://twitter.com/takurinton/status/1438688299388862467?s=20

Preact では軽量化のためもあり、ユーザーが指定したイベントやセレクタを愚直に実DOMに反映していきますが、React では内部でごにゃごにゃやってくれています。自分もまだしっかりコードが読めているわけではないので、そこまでしっかり把握しているわけではないのですが、どうやら意外と Preact と React には差があることがわかりました。

まとめ

ライブラリを使う前には、ドキュメントをしっかり読んだり、特に今回みたいに似てるライブラリを使う時にはそのライブラリとの差はなんなのかについてしっかり確認し、特性を掴んだ上で使用するようにしましょう。
Preact は主に、ネイティブのブラウザのイベントをそのまま実行していますが、React はどうやら中でいろいろ動作が行われていること、React の JSX 記法で書きたかったら、preact/compat を噛ませないといけないことなどがわかりました。
Preact は非常に軽量で、Jason Miller 氏による過剰なまでの最適化が行われているため、非常に面白い技術です。自分もこれから小さいものや、プロトコーディングをするときなどは積極的に使用していきたいなと思いました。

おしまい