registerで管理している要素にrefを渡した結果
投稿日: 2025年03月05日
ハマりました🥺
registerを使うことでフォーム要素のrefを介して直接操作できることはなんとなく理解していましたが、実際の実装において別途refを渡してしまうと問題が発生するとは思っていませんでした。
AIも教えてくれなかった。。
私みたいに時間溶かすともったいないので頭の片隅にでも置いておいてください。
register
で管理している要素に ref
を上書きすると正常に動かない!!
渡してもエラー吐かないから厄介です!!
フォーム管理はreact-hook-form、バリデーションはzodを使いました。
ボタンを押すとtextareaの中に採番した番号が加わって、最後にフォーカスするという操作をしたかったです。
useRefをつかってフォーカスすることになるのでrefを渡したかったのですがハマりました。
"use client";
import { useRef } from "react";
import { useAddAritcleForm } from "../_hooks/useAddAritcleForm";
//省略
const {
register,
} = useAddAritcleForm();
const textareaRef = useRef<HTMLTextAreaElement>(null);
//省略
<Textarea
label="作り方"
disabled={isSubmitting}
id="tips"
placeholder="作り方を入力してください"
errors={errors.tips}
{...register("tips")}
ref={textareaRef}
/>
これNGです。watch("tips")
してもundefined
になって、なんで?え。なんで?(困惑)でした。
工夫が必要です。。
registerをそのまま渡さず、一度分解してuseRefと組み合わせる必要があります。
import { useTextInsert } from "../_hooks/useTextInsert";
import { useAddAritcleForm } from "../_hooks/useAddAritcleForm";
//省略
const {
register,
setValue,
watch,
} = useAddAritcleForm();
//useTextInsert内でconst textareaRef = useRef<HTMLTextAreaElement>(null);と宣言している
const { textareaRef, insertText } = useTextInsert({
value: watch("tips") ?? "",
setValue: val => setValue("tips", val),
});
// refは内部管理用、restにはイベントハンドラを含む
const { ref, ...rest } = register("tips");
//省略
<div className="relative">
<Textarea
label="作り方"
disabled={isSubmitting}
id="tips"
placeholder="作り方を入力してください"
errors={errors.tips}
{...rest} // React-hook-formの管理用props
ref={e => {
ref(e); // React-hook-formにrefを渡してフォーム管理を維持
textareaRef.current = e; //useTextInsertで参照するためのrefを設定
}}
/>
<div className="absolute bottom-3 right-1 w-[100px]">
<Button
type="button"
onClick={() => {
const currentText = watch("tips");
const lines = currentText ? currentText.split("\n") : [];
const length = lines.length;
const newText = `${length > 0 ? "\n" : ""}${length + 1}. `;
insertText(newText);
}}
>
➕ 手順
</Button>
</div>
</div>
これでuseRef使えます!!
なんでundefined??凡ミスしてる?ハテナが止まらなくて、AIに聞くも答えに行き着かず。
もしや。。。register渡してるのにさらにref渡して重複してるかも・・これ問題ある気がするけどどう?って聞くと「その通りです!こうしたらいいです!」って来るコードも同じこと繰り返しててめっちゃつまらん漫才してるみたいになってました。
AIでコード書ける人が逆にすごいと思う今日この頃です。
結構使えないAI、結局自己解決することばかりです。
コードが長くて省略して過不足ありますがrefの箇所だけみてくださいw
参考になれば。