はじめに
React や Next.js でフォームを扱うとき、<textarea>
の状態が連動してしまうことがあります。
個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。
本記事では、文字が連動してしまう理由と、それを防ぐ方法について簡単にまとめます。
書こうと思ったきっかけ
受講しているITスクールのハッカソンの開発の一環で、UIを整える作業中に「2つのテキストエリアが同じ内容になってしまう」現象に遭遇しました。忘れないように原因と対処法を記録しておきます。
修正後の画面
内容
文字が連動してしまう理由
<textarea>
の文字が連動していた原因は、2つのテキストエリアが同じ状態変数 message
を使っていたことです。
具体的にはこのようなコードになっていたためです:
const [message, setMessage] = useState("");
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
この場合、どちらかの textarea
を編集すると message
の値が更新され、それが両方に反映されるため、入力が「連動してしまう」状態になります。
2つの <textarea>
コンポーネントが、同じ状態変数 message
を共有していることが原因です。
const [message, setMessage] = useState("");
この状態変数を両方の textarea
に割り当てると、どちらかに入力した値がもう一方にも即時反映されてしまいます。
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
解決方法:状態を分ける
それぞれのテキストエリアに独立したステートを用意することで、連動を防げます。
const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");
そして各 textarea
を以下のように個別に設定します:
{/* 今日の日記 */}
<textarea
value={diaryMessage}
onChange={(e) => setDiaryMessage(e.target.value)}
/>
{/* さぶちゃんのエール */}
<textarea
value={cheerMessage}
onChange={(e) => setCheerMessage(e.target.value)}
/>
まとめ
複数のフォーム要素が同じ状態を共有していると、意図せずに値が連動してしまいます。
UIの動きを分けたい場合は、それぞれ別の状態変数を使うことが大切です。
今回のようなテキストエリアの例に限らず、フォーム全体の状態管理でも応用できる考え方なので、覚えておきたいと思いました...!