useEffect内调用异步方法仍报Objects are not valid as a React child错误
问题根因
- Promise.all使用错误:
getDocInfo本身返回的是存储文档数据的一维数组,你将其放在数组中传入Promise.all,最终得到的res是[数组]的嵌套结构,这就导致你存入docsWithInfo.arr的数据实际是二维数组,下游组件SignItem如果直接遍历该数组就会出现异常。 - useEffect依赖缺失:你当前的useEffect依赖数组为空,只会在组件首次挂载时执行,如果组件挂载后
props.unsignedDocuments才加载完成,或者后续发生更新,不会重新触发数据请求,最终拿到的是空数组。 - 组件顶层重复实例化控制器:
const userController = new UserController()写在组件顶层,每次组件重渲染都会生成新的控制器实例,造成不必要的性能损耗。 getSignDocData无兜底返回:当查询不到匹配数据时函数返回undefined,虽然你当前做了非空判断,但存在潜在异常风险。
修复代码
import { useState, useEffect, useMemo } from 'react' const UnsignedDocuments = (props) => { const [docsWithInfo, setDocsWithInfo] = useState({arr: []}) // 缓存控制器实例,避免重复生成 const userController = useMemo(() => new UserController(), []) useEffect(() => { const getDocInfo = async () => { // 优化:批量生成所有请求一次性执行,比循环await性能更高 const requestList = props.unsignedDocuments.map(item => userController.getSignDocData(item.multilateralId) ) const docList = await Promise.all(requestList) // 过滤掉空值 return docList.filter(Boolean) } const getInfo = async () => { const temp = await getDocInfo() setDocsWithInfo({arr: temp}) } // 仅当有未签名文档时才发起请求 if(props.unsignedDocuments?.length){ getInfo(); } // 补全依赖项,props更新时自动重新拉取数据 }, [props.unsignedDocuments, userController]); return ( <Accordion bsPrefix='seguridata' style={{'position': 'inherit'}}> <Accordion.Header>Por Firmar <Badge style={{'marginLeft': '2rem'}} bg="dark">x</Badge></Accordion.Header> <Accordion.Body> <Accordion flush><SignItem key={1} docsWithInfo={docsWithInfo.arr}/></Accordion> </Accordion.Body> </Accordion> ) }
注:getSignDocData是UserController类的原生方法,不要放在组件内部定义,直接移到UserController类的实现中即可,记得增加兜底返回return null避免查询无结果时返回undefined
内容的提问来源于stack exchange,提问作者CrappyCoder
相关产品推荐
相关产品推荐

