React组件在useEffect完成前渲染导致子组件数据为空问题求助
处方列表加载异常问题修复方案
问题现象
父组件OwnPrescriptionsPanel通过useEffect调用接口获取数据,传递给子组件PrescriptionsList后,子组件始终为空,仅页面刷新后才能正常加载数据。
核心问题与修复步骤
1. 子组件列表key值不唯一,导致React渲染失效
子组件遍历处方列表时,使用drugId作为元素key,而一个处方可能对应多个药品,会出现key重复的情况,React无法正确识别列表元素的唯一性,进而阻止组件更新。
错误代码:
const pastPrescriptionsList = pastPrescriptions.map((d) => ( <div value={d} onClick={() => handlePrescriptionClick(d)} key={d.drugId} className="prescriptionListItem" > ... </div> ));
修复:改用处方的唯一标识prescriptionId作为key:
const pastPrescriptionsList = pastPrescriptions.map((d) => ( <div value={d} onClick={() => handlePrescriptionClick(d)} key={d.prescriptionId} className="prescriptionListItem" > ... </div> ));
2. 父组件去重逻辑误用filter方法
父组件用filter遍历数据实现去重,filter的设计目的是过滤元素并返回新数组,而非执行遍历操作,写法不规范且可能引发隐性问题。
错误代码:
var resArr = []; response.data.filter(function (item) { var i = resArr.findIndex((x) => x.prescriptionId === item.prescriptionId); if (i <= -1) { resArr.push(item); } return null; }); setPastPrescriptions(resArr);
修复:改用reduce实现更规范的去重逻辑:
const uniquePrescriptions = response.data.reduce((acc, item) => { if (!acc.find(x => x.prescriptionId === item.prescriptionId)) { acc.push(item); } return acc; }, []); setPastPrescriptions(uniquePrescriptions);
3. 校验sessionStorage中id的有效性
父组件挂载时直接获取sessionStorage.getItem("id"),若组件通过路由跳转挂载而非刷新,可能存在id未存入的情况,导致请求参数为空,后端返回空数据。
修复:在请求前校验id是否存在,同时添加错误捕获:
useEffect(() => { const patientId = sessionStorage.getItem("id"); if (!patientId) { // 处理未登录场景,例如跳转至登录页 setIsBusy1(false); return; } Axios.post( "http://localhost:3001/getpatientprescriptions", { id: patientId }, { headers: { "Content-Type": "application/json" } } ).then((response) => { const uniquePrescriptions = response.data.reduce((acc, item) => { if (!acc.find(x => x.prescriptionId === item.prescriptionId)) { acc.push(item); } return acc; }, []); setPastPrescriptions(uniquePrescriptions); setIsBusy1(false); }).catch(err => { console.error("获取处方数据失败:", err); setIsBusy1(false); }); }, []);
4. 添加空状态提示
当处方列表为空时,子组件可添加友好提示,避免页面空白:
return ( <div className="prescriptionsListContainer"> <div className="viewPrescriptionsLabel">{heading}</div> <div className="prescriptionsContainer"> {pastPrescriptionsList.length > 0 ? pastPrescriptionsList : <div>暂无处方记录</div>} </div> {/* 模态框代码保持不变 */} </div> );
内容的提问来源于stack exchange,提问作者Nalindaka Hettiarachchi
相关产品推荐
相关产品推荐

