MUI Select非受控转受控报错 工单编辑表单默认值不生效如何修复
问题根源
该报错的核心原因是MUI Select组件的value属性初始值为undefined,被识别为非受控组件,等异步请求拿到工单数据后value变为有效值,又切换为受控模式,MUI不允许组件在生命周期内切换控制状态。同时代码还存在状态源不统一、重复声明状态、提交参数缺失等问题,按以下步骤修复即可:
修复步骤
- 清理重复状态,给ticket设置初始值
你当前代码重复声明了两次ticket状态,先删除重复声明,再给ticket设置符合TicketFullDTO结构的初始值,避免status初始为undefined:
// 删除重复的ticket useState声明,修改为带初始值的版本 const [ticket, setTicket] = useState<TicketFullDTO>({ title: "", status: "", submitDate: null }); // 如果你不需要独立的status状态可以直接删除下面这行 // const [status, setStatus] = useState<string>("");
- 统一Select的状态源
当前Select的value绑定ticket.status,但onChange却更新独立的status状态,两者完全脱节,直接将Select的变更同步到ticket对象即可:
<Select labelId="status-label" id="status-helper" value={ticket.status} // 初始为非undefined的空字符串,全程受控 onChange={(e) => setTicket({...ticket, status: e.target.value as string})} required > {ticketStatusList.map((element) => ( <MenuItem key={element.code} value={element.code}> {/* 新增key避免React列表警告 */} {element.name} </MenuItem> ))} </Select>
- 修复日期字段和提交逻辑
当前日期字段用了defaultValue属于非受控模式,改为受控绑定,同时补全提交参数:
{/* 日期输入框修改为受控模式 */} <TextField label="Submit Date" id="submit-date" type="date" value={submitDate ? submitDate.format("YYYY-MM-DD") : ""} onInput={(e) => setSubmitDate(moment(e.target.value))} InputLabelProps={{ shrink: true }} />
// 提交函数补全参数 const formSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); // 合并日期字段到提交数据 const submitData = {...ticket, submitDate}; updateTicket(requestParams.id, submitData) .then(({ data }) => { console.log(data.title); history.replace("/support"); }) .catch((err) => { console.log(err); }); }; // form标签绑定正确的提交函数 // <form onSubmit={formSubmit}>
- (可选)添加加载状态优化体验
在异步请求未完成前禁用表单,避免用户提前操作:
const [loading, setLoading] = useState(true); useEffect(() => { Promise.all([getTicketStatusTypes(), getTicket(requestParams.id)]) .then(([statusResp, ticketResp]) => { setTicketStatusList(statusResp.data); setTicket(ticketResp.data); setLoading(false); }) .catch(err => console.error(err)) }, []);
给所有表单组件加上disabled={loading}属性即可。
修改完成后,Select组件从首次渲染开始就是受控模式,异步数据返回后会自动匹配选中对应的状态选项,不会再抛出控制态切换错误。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

