MUI X Data Grid:修复验证通过时点击外部仍恢复原值的问题
MUI X Data Grid邮箱验证恢复原值问题修复
问题描述
我在MUI X Data Grid里做邮箱字段验证,目前验证功能正常,但只有按Esc键时,验证失败的单元格才会恢复原值。参考MUI官方验证示例(验证失败显示Tooltip提示)修改后,我尝试用onBlur和stopCellEditMode实现:验证失败且点击单元格外部时恢复原值,但现在有个新问题——就算邮箱验证通过,点击外部也会把内容恢复成原值;删掉handleBadEmail函数就能正常保存邮箱内容。
现有代码
let promiseTimeout; const validateEmail = (email) => { return new Promise((resolve) => { promiseTimeout = setTimeout(() => { let emailWorks = false; if ( String(email) .toLowerCase() .match( /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ) ) { emailWorks = true; } resolve(emailWorks ? null : `${email} is not a valid email.`); }, Math.random() * 500 + 100); // 模拟网络延迟 }); }; const StyledTooltip = styled(({ className, ...props }) => ( <Tooltip {...props} classes={{ popper: className }} /> ))(({ theme }) => ({ [`& .${tooltipClasses.tooltip}`]: { backgroundColor: theme.palette.error.main, color: theme.palette.error.contrastText, }, })); function NameEditInputCell(props) { const { error, value } = props; const apiRef = useGridApiContext(); const handleBadEmail = async () => { let oldValue = apiRef.current.setEditCellValue({ id: props.id, field: "email", value: value, }); if (error) { apiRef.current.stopCellEditMode({ id: props.id, field: "email", value: oldValue, ignoreModifications: false, }); } }; return ( <StyledTooltip open={!!error} title={error}> <GridEditInputCell onBlur={handleBadEmail} {...props} /> </StyledTooltip> ); } function renderEditName(params) { return <NameEditInputCell {...params} />; } const ColDefs = () => { const preProcessEditCellProps = async (params) => { const errorMessage = await validateEmail(params.props.value.toString()); return { ...params.props, error: errorMessage }; }; return { columns: [ { field: "col1", headerName: "Seller", flex: 1, editable: true, }, { field: "email", headerName: "Email", flex: 1, editable: true, preProcessEditCellProps, renderEditCell: renderEditName, }, ] }; }
问题原因与修复方案
问题根源
handleBadEmail函数开头调用的setEditCellValue会强制把单元格值设为初始的value,这就导致不管验证是否通过,用户输入的内容都会被提前覆盖,后续的error判断完全失效。
修复代码
修正NameEditInputCell的逻辑,只有验证失败时才恢复原值:
function NameEditInputCell(props) { const { error, id, field, value: initialValue } = props; const apiRef = useGridApiContext(); const handleBadEmail = () => { // 仅当验证失败时,恢复到编辑前的初始值 if (error) { apiRef.current.stopCellEditMode({ id, field, value: initialValue, // 忽略当前修改,直接恢复初始状态 ignoreModifications: true, }); } }; return ( <StyledTooltip open={!!error} title={error}> <GridEditInputCell onBlur={handleBadEmail} {...props} /> </StyledTooltip> ); }
额外优化:清理定时器避免内存泄漏
在使用validateEmail的组件中添加清理逻辑,防止组件卸载后定时器仍在运行:
import { useEffect } from 'react'; // ... 其他代码 ... const YourDataGridComponent = () => { useEffect(() => { return () => { if (promiseTimeout) { clearTimeout(promiseTimeout); } }; }, []); // ... 渲染DataGrid的逻辑 ... };
内容的提问来源于stack exchange,提问作者thePunctuator
相关产品推荐
相关产品推荐

