4
0

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.

株式会社エイチームコマーステックのkazzです。

タイトルの通り、今回は React 用のフォームライブラリである react-final-form から react-hook-form への移行について、開発での実体験を交えながら軽めにお話しできたらと思います。

なぜ移行するのか

フォームの開発をしやすくするために react-final-form を使って開発をしていましたが、1年半ほど改修を繰り返す中で、 react-final-form の以下の点が目につくようになりました。

  • 不具合が多く、かつ中々対応されない
  • 直近のcommit・リリースが少ない
  • 比較的、ドキュメントが不充実

要するに、メンテが不十分であることが要因で色々と不都合が起こるようになってきました。そして、大きめの改修をキッカケに、 react-hook-form への移行を決意しました。

hook-form の選定

hook-form でシステムに必要な機能要件も満たしていそうであり、かつ実行パフォーマンスに関してもバンドルサイズもトータルで僅かに減で、非制御コンポーネントにより再レンダリングを抑えやすくなったため、パフォーマンス改善も見込めました。

react-final-form + final-form react-hook-form (formik)
bundled size (minified) 25.8kB 25.1kB 44.3kB
control 制御コンポーネント 非制御コンポーネント 制御コンポーネント
メンテナンス 1年で4commits たくさん ほぼなし
ドキュメント(主観) 見ずらい 見やすい 見やすい

移行作業

1. コンポーネントの作り直し

共通化しているコンポーネント・処理が final-form にがっつり依存していることが判明。該当のフォームだけを順々に直していく想定でいましたが、共通部分からの作り直しが必要になってしまいました。

このフェーズでは、新たなディレクトリへ hook-form でも使えるコンポーネントの実装を行いました。合わせて、formとUIの疎結合化も進めてます。

これを、

共通コンポーネント
// こんな感じで、外枠から final-form に依存している
import { Field } from 'react-final-form';
...
const InputText = () => {
    return <Field>...</Field>
}

このようにUIとformに分けて実装することで、処理の見通しも良くなり、共通化部分とformが疎結合になりました。

共通コンポーネント
import { useController } from 'react-hook-form';

// 純粋なUIコンポーネント
const InputText = ({onChange, onBlur, ref, ...}) => {
    return <input onChange={onChange} onBlur={onBlur} ref={ref} />
}

// formに関わる処理をラップしたコンポーネント
const InputTextForHookForm = ({control, registerName, ...rest}: {control: Control, control: string ...}) => {
    const { field } = useController({ control, name: registerName});
    return <InputText {...field} />
}

hook-form は イベントハンドラーやrefを正しく末端まで引き継いであげればライブラリの機能をしっかり使えるので、その点はこのformとUIの疎結合化はしやすかったかなと思います。

2. form部分の作り替え

これは一律でやるもの予定はなく、改修のたびに置き換えていくよう進めてます。

非制御コンポーネントの扱いは最初は慣れませんでしたが、 useWatch のようなAPIを活用していくことで、欲しい部分に再レンダリングを挟みつつレンダリングの回数を抑える実装ができるので使い勝手は良いです。

制御・非制御コンポーネントの違いを先に理解しておくのはMUSTかと思います。

3. 後処理

置き換えを進める中で不要になり次第既存のコンポーネントを消していったり、ライブラリ自体の削除をします。final-form はそれなりにサイズも大きいので、忘れず行います。

最後に

不具合やドキュメントの見づらさから、開発体験を大きく落としている部分だと感じながら開発していたので、移行作業ができていることは嬉しく思います。

最近は、React も Next.js もどんどん新機能が出てくる中で、メンテ不足により機能追従がされなくなる不安もあったため、今後のためを思い移行を進めました。

今回は全体の流れをさらっと説明しましたが、各項目でここをもっと具体的に知りたいなど要望があれば、別記事で出そうかなと思います。

次回アドベントカレンダーの投稿は、@o93 さんの 「誤差と あいまいさと 不確かさと」 です!

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?