この記事はビビッドガーデン Advent Calendar 2021の7日目です。
こんにちは、食べチョクを開発している遠藤です。
今回はbuttonのtype属性を書いていないおかげで、謎の挙動にハマりました。
発生していた事象
何が起きていたかを話します。
弊社では、Reactを利用して管理画面を作成しています。
サンプルコードは、以下の通りです。
const handleOnChange = (e) => {
...
}
const handleOnClick = (e) => {
alert("Enter押すとこいつが反応するんだよな")
}
...
...
<form>
<input type="text" ... onChange={handleOnChange} />
...
...
...
<button ... onClick={handleOnClick}>
追加する
</button>
</form>
text型でEnterキーを押すとなぜか、handleOnClick
呼ばれてしまいます🤔
正直全然見当違いの場所でイベントが発火しているために、e.preventDefault()
で対応する方針で行っていましたが、どうもうまくいかなかったです。
調べていくと、本家のReactでもIssueが報告がされていました。
原因
さて、原因です。
buttonのtype属性を書いていないために起こる挙動が原因です。
ここからはリファレンスを参照します。
type
に関連付けられたボタンに指定されていない場合、またはこの属性が空であったり不正な値であったりした場合の既定値です。
このボタンの既定の動作です。以下の値が指定可能です。
submit: このボタンはフォームのデータをサーバーへ送信します。これはこの属性が
reset: このボタンはすべてのコントロールを初期値に初期化します。 と同様です。 (この動作はユーザーを困らせる傾向があります。)
button: ボタンには既定の動作がなく、既定では押されても何も行いません。この要素のイベントを待ち受けし、イベントが発生すると起動されるクライアント側スクリプトを設定することができます。
そう、この挙動です。
submit: このボタンはフォームのデータをサーバーへ送信します。これはこの属性が
に関連付けられたボタンに指定されていない場合、またはこの属性が空であったり不正な値であったりした場合の既定値です。
つまり、form内の場合は、Enterを押した場合の送信ボタンになります。
ボタンがサーバーにデータを送信するためのものでない場合は、 type 属性を button に設定することを忘れないでください。さもないと、フォームデータを送信して (存在しない) レスポンスを読み込み、文書の現在の状態を破棄してしまうおそれがあります。
注意文があるぐらい、罠な挙動になっています。
対策
弊社では同じ過ちを繰り返さないためにも、対策を行います。
今回はeslintでbuttonのtype属性がない場合は、指摘するルールがあったので、それを適用しました。
これでこの話は終わりです。
最後に
弊社では一度問題が発生したら、対策していきます。
問題が発生したら、解決策を練ることが好きな人のための求人があります。
よろしくお願いします!!!