React组件VerseForm报错:传入verseObj.version_id为string,预期为object
解决React组件Prop类型错误:Invalid prop
verseObj.version_id of type string supplied to VerseForm, expected object 问题背景
我正在开发一款可添加经文的全栈公共祈祷日志应用,此前创建功能运行正常,近期未修改相关代码,但表单渲染时始终出现以下错误:
Invalid prop
verseObj.version_idof typestringsupplied toVerseForm, expectedobject.
相关代码片段:
// VerseForm.js useEffect(() => { getVersions().then(setVersions); if (verseObj.id) { getSingleVerse(verseObj.id).then((response) => { setCurrentVerse(response); // setSelectedVersion(verseObj.version_id.id); }); } }, [verseObj]); }; const handleSubmit = (e) => { e.preventDefault(); if (verseObj.id) { updateVerse(user, currentVerse, verseObj.id) .then(() => router.push('/')); } else { const payload = { ...currentVerse }; createVerse(payload, user).then(setCurrentVerse(initialState)); } }; VerseForm.propTypes = { verseObj: PropTypes.shape({ id: PropTypes.number, verse: PropTypes.string, content: PropTypes.string, version_id: PropTypes.shape({ id: PropTypes.number, label: PropTypes.string, }), }), user: PropTypes.shape({ uid: PropTypes.string, id: PropTypes.number, }).isRequired, }; VerseForm.defaultProps = { verseObj: initialState, };
问题原因
错误核心是父组件传给VerseForm的verseObj.version_id是字符串类型,但组件的propTypes明确要求它是包含id和label的对象。常见触发场景:
- 后端接口返回的
version_id格式变更,从关联对象变成了纯ID字符串 - 父组件传递
verseObj时,误传了version_id.id而非完整对象 - 本地存储/状态管理中保存的
verseObj数据格式异常
修复方案
1. 排查数据源
- 检查父组件传递
verseObj的逻辑,确认version_id是否为完整对象(比如列表项点击时,是否把整个版本对象传进来,而非只传ID) - 查看
getSingleVerse接口的返回值,打印response.version_id确认格式是否符合预期
2. 组件内添加格式修正逻辑
如果无法快速修改数据源,可以在VerseForm内对传入的verseObj做容错处理:
useEffect(() => { getVersions().then(setVersions); if (verseObj.id) { // 修正version_id格式:如果是字符串/数字,转为符合要求的对象 const correctedVerseObj = { ...verseObj, version_id: typeof verseObj.version_id !== 'object' ? { id: Number(verseObj.version_id), label: '' } : verseObj.version_id }; getSingleVerse(correctedVerseObj.id).then((response) => { setCurrentVerse(response); // 如果需要匹配版本名称,从已获取的versions列表中查找补全 const matchedVersion = versions.find(v => v.id === correctedVerseObj.version_id.id); if (matchedVersion) { setSelectedVersion(matchedVersion.id); setCurrentVerse(prev => ({ ...prev, version_id: matchedVersion })); } }); } }, [verseObj, versions]);
3. 调整propTypes兼容多种格式(可选)
如果业务上允许version_id临时为数字/字符串,可以放宽propTypes限制,同时在组件内统一转换格式:
VerseForm.propTypes = { verseObj: PropTypes.shape({ id: PropTypes.number, verse: PropTypes.string, content: PropTypes.string, version_id: PropTypes.oneOfType([ PropTypes.shape({ id: PropTypes.number, label: PropTypes.string, }), PropTypes.string, PropTypes.number ]), }), user: PropTypes.shape({ uid: PropTypes.string, id: PropTypes.number, }).isRequired, };
4. 修正提交逻辑
如果后端接口只需要version_id的ID值,提交时要从对象中提取:
const handleSubmit = (e) => { e.preventDefault(); // 统一处理提交的version_id格式 const formatPayload = (data) => ({ ...data, version_id: data.version_id.id || data.version_id }); if (verseObj.id) { updateVerse(user, formatPayload(currentVerse), verseObj.id) .then(() => router.push('/')); } else { createVerse(formatPayload(currentVerse), user) .then(() => setCurrentVerse(initialState)); } };
内容的提问来源于stack exchange,提问作者Soothingcube3
相关产品推荐
相关产品推荐

