React中点击自定义Select组件触发表单required验证异常求助
解决点击自定义SelectBox触发表单必填验证的问题
问题原因
- 按钮默认类型触发表单提交:SelectBox组件中用于展开下拉的按钮未指定
type="button",HTML里按钮默认类型为submit,点击时会触发表单提交逻辑,进而触发必填字段的验证提示。 - 多余的onChange绑定:SelectBox最外层的
<div>绑定了onChange事件,属于不必要的冗余绑定,会造成额外的事件触发干扰。
解决方案
1. 修正SelectBox触发按钮的类型
在SelectBox组件的展开按钮上明确添加type="button",避免触发表单提交:
// SelectBox组件内的触发按钮修改 <button type="button" onClick={openDropDown}> {selectedValue === undefined || selectedValue === '' ? placeHolder : selectedValue} </button>
2. 移除SelectBox外层div的冗余onChange绑定
删除SelectBox组件最外层div上的onChange属性,该元素无需监听change事件:
// 原代码 <div onChange={onChange} ref={selectRef}> // 修改后 <div ref={selectRef}>
3. 修正主文件的表单嵌套结构(推荐)
主文件中表单的DOM嵌套存在错误,修正后确保表单标签正确包裹所有表单控件:
// 主文件表单部分修改 <form> <div id="content-div"> <label htmlFor="nameid">Name</label> <TextField required onChange={SavingDetails} value={userDetails.username} id="nameid" name="username" type="text" /> </div> <div id="content-div"> <label htmlFor="num">Phone</label> <TextField required onChange={SavingDetails} value={userDetails.userphone} id="num" name="userphone" type="phone" /> </div> </form> <SelectBox onChange={SavingDetails} selectBoxWidth="80%" placeHolder="Choose" > <MenuItem value="None">None</MenuItem> {menuItems.map((val, ind) => ( <MenuItem value={val} key={ind}>{val}</MenuItem> ))} </SelectBox>
完整修改后的SelectBox组件代码
import { useState, useRef, useEffect, Children, cloneElement, useCallback } from "react"; export function MenuItem({ value, children, onSelect, isSelected }) { return ( <button type="button" value={value} onClick={() => onSelect(value)} className={isSelected ? 'active-dd-btn' : ''} > {children} </button> ); } export function SelectBox({ placeHolder = 'Placeholder..', children, onChange }) { const selectRef = useRef(null); const [isOpen, setOpen] = useState(false); const [selectedValue, setSelectedValue] = useState(""); const HandleChange = useCallback( (value) => { onChange(value); setSelectedValue(value); setOpen(false); }, [onChange] ); function openDropDown() { setOpen(!isOpen); } useEffect(() => { const handleClickAway = (event) => { if (selectRef.current && !selectRef.current.contains(event.target)) { setOpen(false); } }; document.addEventListener("mousedown", handleClickAway); return () => { document.removeEventListener("mousedown", handleClickAway); }; }, []); return ( <div ref={selectRef}> <button type="button" onClick={openDropDown}> {selectedValue === undefined || selectedValue === '' ? placeHolder : selectedValue} </button> {isOpen && ( <div id="dropdown"> {Children.map(children, (child) => cloneElement(child, { onSelect: HandleChange, isSelected: child.props.value === selectedValue }) )} </div> )} </div> ); }
内容的提问来源于stack exchange,提问作者Vicky X
相关产品推荐
相关产品推荐

