React中使用react-bootstrap/Modal结合react-hook-form实现表单提交并传递数据至函数的问题及解决方法
解决react-hook-form + react-bootstrap Modal的表单提交问题
我之前也踩过这个坑!当你把<form>放在<Modal>组件外面时,react-bootstrap的Modal内部结构会把表单的上下文给隔开,导致react-hook-form没办法正确捕获表单里的输入控件,自然也就没法通过handleSubmit把收集到的数据传给你的update函数。
先看看最开始有问题的代码:
<form onSubmit={handleSubmit(update)}> <Modal show={show} onHide={handleClose}> <Modal.Header closeButton> <Modal.Title>Edit</Modal.Title> </Modal.Header> <Modal.Body> <label>Description</label> <input name="message" type="text" ref={register} placeholder="description"/> </Modal.Body> <Modal.Footer> <button variant="secondary" onClick={handleClose}> Cancel </button> <button type="submit" variant="primary" onClick={update}> Edit </button> </Modal.Footer> </Modal> </form> // 异步处理部分 const update = (data) => { (async () => { console.log("data", data) })() }
解决方案
把<form>标签移到<Modal>内部,让它包裹住Modal的所有子组件(Header、Body、Footer),这样表单就能和内部的输入控件建立正确的关联,react-hook-form就能正常工作了。
修正后的代码:
<Modal show={show} onHide={handleClose}> <form onSubmit={handleSubmit(update)}> <Modal.Header closeButton> <Modal.Title>Edit</Modal.Title> </Modal.Header> <Modal.Body> <label>Description</label> {/* 别忘了加上react-hook-form的register引用 */} <input name="message" type="text" ref={register} placeholder="description" /> </Modal.Body> <Modal.Footer> <button variant="secondary" onClick={handleClose}> Cancel </button> {/* 这里不需要额外加onClick={update},onSubmit已经会触发update并传数据 */} <button type="submit" variant="primary"> Edit </button> </Modal.Footer> </form> </Modal> // 优化后的异步update函数 const update = async (data) => { console.log("data", data); // 这里写你的API调用逻辑,比如: // try { // await fetch('/api/your-endpoint', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(data) // }); // handleClose(); // 提交成功后关闭弹窗 // } catch (err) { // console.error('提交失败:', err); // } };
额外小提示
- 提交按钮不要同时加
onClick={update},不然会导致update函数被调用两次(一次是点击事件,一次是表单提交事件),只保留type="submit"就够了。 - 可以直接把
update写成异步函数,不用嵌套立即执行函数,代码更简洁易读。 - 别忘了给输入框加上
ref={register},不然react-hook-form没法收集这个输入框的数据(修正后的代码里我补上了这个)。
内容的提问来源于stack exchange,提问作者JasonMimo
相关产品推荐
相关产品推荐

