如何在React-Admin中用DataProvider实现服务端异步校验?
1. 借助dataProvider实现邮箱唯一性校验(UserCreate组件)
直接使用React-Admin官方提供的useDataProvider钩子替代自定义fetch,编写异步校验函数:
import { useDataProvider } from 'react-admin'; import { Create, SimpleForm, TextInput, required } from 'react-admin'; const UserCreate = () => { const dataProvider = useDataProvider(); const checkEmailIsUnique = async (value) => { if (!value) return; // 空值校验交给required规则处理 try { const { total } = await dataProvider.getList('users', { filter: { email: value }, pagination: { page: 1, perPage: 1 }, // 仅需判断是否存在,无需返回全部数据 sort: { field: 'id', order: 'ASC' }, }); return total > 0 ? '该邮箱已被注册' : undefined; } catch (err) { return '邮箱唯一性校验失败'; } }; return ( <Create> <SimpleForm> <TextInput source="email" validate={[required(), checkEmailIsUnique]} /> {/* 其他表单字段 */} </SimpleForm> </Create> ); }; export default UserCreate;
通过dataProvider.getList查询匹配输入邮箱的用户记录,根据返回的total值判断是否重复,完全遵循React-Admin官方数据交互规范。
2. 适配PartnerNameInput组件支持更新场景
通过useRecordContext钩子获取当前编辑的记录(更新场景下存在值,创建场景为null),在校验时动态添加排除当前记录ID的条件:
import { useDataProvider, useRecordContext } from 'react-admin'; import { TextInput, required } from 'react-admin'; const PartnerNameInput = (props) => { const dataProvider = useDataProvider(); const currentRecord = useRecordContext(); // 更新场景返回当前编辑记录,创建场景为null const checkPartnerNameUnique = async (value) => { if (!value) return; try { const filter = { name: value }; // 更新场景:排除当前记录的ID,避免把自身判定为重复 if (currentRecord?.id) { filter.id = { ne: currentRecord.id }; } const { total } = await dataProvider.getList('partners', { filter, pagination: { page: 1, perPage: 1 }, sort: { field: 'id', order: 'ASC' }, }); return total > 0 ? '该合作伙伴名称已存在' : undefined; } catch (err) { return '名称唯一性校验失败'; } }; return <TextInput {...props} validate={[required(), checkPartnerNameUnique]} />; }; export default PartnerNameInput;
现在这个组件可以直接在Create和Edit组件中复用:
- 创建场景:直接校验名称是否重复
- 更新场景:自动排除当前记录,仅校验其他记录是否存在同名
注:如果你的dataProvider不支持ne(不等于)操作符,可根据后端API要求调整filter格式(比如部分后端用id__ne作为参数)。
内容的提问来源于stack exchange,提问作者qbantek
相关产品推荐
相关产品推荐

