FormikというReactのフォームライブラリがあり、それでFormを組んでいてハマったのでメモ。
欲求
Formの中にButtonを配置せず、『外側にサブミットボタンを配置したい』
ようはフォームの外側にonSubmit
なボタンコンポーネントを作って、それを押したら目的のフォームがsubmitされるようにしたい。
解決策
react-final-formのFAQみてたら書いてあった。
① formのDOM取得してEventをディスパッチする
Via document.getElementById()
<button onClick={() => { document.getElementById('myForm').dispatchEvent(new Event('submit')) // ✅ }}>Submit</button> <form id="myForm" onSubmit={handleSubmit}> ...fields go here... </form>
なるほど!
② クロージャでsubmt変数を定義してそこにsubmit関数を代入する
Via Closure
let submit return ( <div> <button onClick={submit}>Submit</button> // ❌ Not overwritten closure value <button onClick={event => submit(event)}>Submit</button> // ✅ <Form onSubmit={onSubmit} render={({ handleSubmit }) => { submit = handleSubmit return <form>...fields go here...</form> }} /> </div> )
たしかに〜
③ そもそもHTML5のform属性を利用できる
これは別途react-final-formのFAQには書いてないけどやってみたらできた別案。
HTML5にはform属性があって、例えばMDNのbutton
のページにはこうある
ボタンに関連付けられた form 要素(form owner)です。 属性値は同一文書内の
ようするにformのid属性と関連付けが出来る
ので、こう書けばform
の中にbutton
がなくともsubmitが可能
<button form='myform'>Submit</button> <form id="myForm" onSubmit={handleSubmit}> ...fields go here... </form>
ReactでFormむずかしい
アプリっぽいUIを作っていて、フォームの送信ボタンをヘッダーの右上(スマホの右上)に設置したくて悩んでいて、この解決方法になんとかたどり着いた。
Reactでフォーム組むのとにかく難しくて、どこに処理書けばいいとかcontrolledかuncontrolledかとかバリデーションとかいろいろある。様々な概念とライブラリの仕様が絡み合うから厳しい気持ちになる。