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

【React Hook Form】二つのフォームの値を連動される方法

Posted at

React Hook Form で、二つのフォームを連動させたい!
ついでに、その値も表示したいなぁ~~

image.png

とりあえず枠組みを用意

React でフォームを用意したい場合、React Hook Form がいいみたい。
<input>useState() をいい感じに管理してくれる。

これを使って、二つのフォームを連動させてみる。

page.tsx
'use client'

import { useForm } from 'react-hook-form'

export default function MyApp() {
  const form = useForm({
    defaultValues: {
      name: '初期値',
    },
  })
  
  const nameValue = form.watch('name')

  return (
    <form>
      <div className="p-4 flex flex-col gap-2">
        <div>
          今の値:
          {nameValue}
        </div>
        <input
          className="input"
          {...form.register('name')}
        />
        <input
          className="input"
          {...form.register('name')}
        />
      </div>
    </form>
  )
}

フォームに React Hook Form を紐づけるには register() メソッドを付与する。
このメソッドは、以下の4つの要素を <input> に付与する。

image.png

また、フォームの値を使用したい場合は watch() メソッドを使用する。
これを使わないと再レンダリングが動かないので注意。

でもこのやり方だと、後のフォームしかうまく動かない。
おそらく二つの EventListener か Observer が競合しているのだろう。
フォームA → フォームB の順番で処理されてしまって、React 側とフォーム側の連動が壊れてしまっている。

Animation.gif

試行錯誤の末

page.tsx
'use client'

import { useForm } from 'react-hook-form'

export default function MyApp() {
  const form = useForm({
    defaultValues: {
      name: '初期値',
    },
  })

  const nameValue = form.watch('name')

  return (
    <form>
      <div className="p-4 flex flex-col gap-2">
        <div>
          今の値:
          {nameValue}
        </div>
        <input
          className="input"
          {...form.register('name', {
            onChange: (e) => {
              form.setValue('name', e.target.value)
            },
          })}
        />
        <input
          className="input"
          {...form.register('name', {
            onChange: (e) => {
              form.setValue('name', e.target.value)
            },
          })}
        />
      </div>
    </form>
  )
}

register() の引数で onChange() として、フォームの値を再度記録しているのがポイント。
そうすることで、値を再度強制的に同期して解決!
(これが最適解かはわからない。。。)

Animation.gif

おわりに

onChange() はコードを読むとバリデーションとか色々なことをやっているみたい。
これってバグなのかな...仕様なのかな...。
ちょっと全コードは追いきれなかった...。

こういう体験をすると Vue がこの辺の処理をいかに隠匿しているかがわかる。
それがいいか悪いかはべつとしt

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