使用Formik开发订餐表单遇双按钮均触发handleSubmit问题求助
问题描述
我用Formik开发订餐项目的表单校验时遇到了问题:表单里设了两个按钮,但不管点哪个都会触发handleSubmit函数。我想让CloseButton关闭表单返回订单列表,可它只会触发Formik的handleSubmit,根本不执行props里的goBack函数(这个函数只是把某个状态设为false)。查了Formik文档也没找到解决办法,相关代码如下:
export default function Checkout(props) { function handleSubmit(event) { // event.preventDefault(); console.log("Hello"); } return ( <Formik initialValues={{ userName: "Hi", street: "", postalCode: "", city: "" }} onSubmit={handleSubmit} > {(props) => ( <Form className={styles["form"]}> <div className={styles["form-control"]}> <div className={styles["form-control__input"]}> <label htmlFor="userName">Your name</label> <Field type="text" name="userName" id="userName"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="street">Street</label> <Field type="text" name="street" id="street"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="postalCode">Postal code</label> <Field type="text" name="postalCode" id="postalCode"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="city">City</label> <Field type="text" name="city" id="city"></Field> </div> </div> <div className={styles["form-actions"]}> <CloseButton type="button" onClick={props.goBack}>Back</CloseButton> <OrderButton type="submit">Confirm</OrderButton> </div> </Form> )} </Formik> ); }
export default function CloseButton(props) { return <button type={props.type} onClick={props.onClick} className={styles["close-button"]}>{props.children}</button>; }
export default function OrderButton(props) { return <button type={props.type} onClick={props.onClick} className={styles['order-button']}>{props.children}</button> }
解决方案
问题根源是变量名冲突:Formik渲染回调里的props把外部组件的props覆盖了。你在<Formik>{(props) => (...)}</Formik>里用props当参数,这里的props是Formik提供的上下文对象,根本不是父组件传给Checkout的props,所以props.goBack其实是undefined,再加上表单的默认行为,点击按钮就触发了提交。
解决方法很简单:
- 把Formik回调里的参数名改成别的,比如
formikProps,避免和外部组件的props重名 - 确保CloseButton的
type="button"正确传递(你的代码已经做到了这一点,默认按钮type是submit,会触发表单提交)
修改后的Checkout组件代码:
export default function Checkout(props) { function handleSubmit(event) { // event.preventDefault(); console.log("Hello"); } return ( <Formik initialValues={{ userName: "Hi", street: "", postalCode: "", city: "" }} onSubmit={handleSubmit} > {(formikProps) => ( // 这里修改参数名 <Form className={styles["form"]}> {/* 表单字段部分不变 */} <div className={styles["form-control"]}> <div className={styles["form-control__input"]}> <label htmlFor="userName">Your name</label> <Field type="text" name="userName" id="userName"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="street">Street</label> <Field type="text" name="street" id="street"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="postalCode">Postal code</label> <Field type="text" name="postalCode" id="postalCode"></Field> </div> <div className={styles["form-control__input"]}> <label htmlFor="city">City</label> <Field type="text" name="city" id="city"></Field> </div> </div> <div className={styles["form-actions"]}> {/* 这里用外部的props.goBack */} <CloseButton type="button" onClick={props.goBack}>Back</CloseButton> <OrderButton type="submit">Confirm</OrderButton> </div> </Form> )} </Formik> ); }
这样修改后,点击CloseButton就会执行父组件传入的goBack函数,不会再触发表单提交了。
内容的提问来源于stack exchange,提问作者ArtemBohak
相关产品推荐
相关产品推荐

