React应用:修复Cannot read properties of undefined错误及内存泄漏
问题分析与解决方案
问题1:Cannot read properties of undefined (reading 'caseNumber')
原因
组件渲染时caseDetail可能为undefined(比如父组件初始未传入值、状态更新过程中短暂为空),导致拼接getCaseNotes的URL时,直接访问caseDetail.caseNumber触发报错。
解决方法
给
caseDetail设置默认值
在组件参数中给caseDetail设置空对象默认值,避免直接访问undefined的属性:export function SubmissionsCaseDetail({caseDetail = {}, setCurrentCaseDetail}) {添加可选链操作符
在拼接URL时使用可选链,确保caseDetail存在时才访问caseNumber:const { run: getCaseNotes } = useFetchye(`${subApiUrl}/case/notes/${caseDetail?.caseNumber}`, { defer: true, credentials: 'include', headers: getDefaultHeaders(), method: 'GET', });组件内条件渲染
在组件开头判断caseDetail是否有效,无效时显示加载状态,避免后续代码执行报错:if (!caseDetail?.caseNumber) { return <div>Loading case details...</div>; }
问题2:组件卸载后更新状态的内存泄漏警告
原因
异步请求(updateCase/getCaseDetail)完成后,组件可能已被卸载,此时调用setResponseMsg或setCurrentCaseDetail等状态更新函数,会触发React的内存泄漏警告。
解决方法
使用挂载状态标记,在异步操作完成后检查组件是否仍处于挂载状态,再执行状态更新:
import { useRef, useEffect } from 'react'; export function SubmissionsCaseDetail({caseDetail = {}, setCurrentCaseDetail}) { const isMounted = useRef(true); // 组件卸载时标记为未挂载 useEffect(() => { return () => { isMounted.current = false; }; }, []); const refreshCaseDetail = async () => { const { data } = await getCaseDetail(); // 检查组件是否仍挂载,未挂载则直接返回 if (!isMounted.current) return; if (data.status === 200) { const caseDetailResult = transformSubmissionsCases(data.body); setCurrentCaseDetail(caseDetailResult.caseDetails[caseDetail.caseNumber]); refreshClicNotes(); } else { setResponseMsg('Error in retrieving case detail'); } }; const callUpdateCase = async () => { const { data } = await updateCase(); if (!isMounted.current) return; if (data.status === 200) { setResponseMsg('Case Updated Successfully'); refreshCaseDetail(); } else { setResponseMsg('Error updating case.'); } setCaseUpdateDtls({}); }; // ...其余代码 }
额外潜在问题:updateCase请求body未更新
原因
原代码中useFetchye的body在组件渲染时就已固定为初始caseUpdateDtls的字符串,后续caseUpdateDtls变化时,请求仍会使用旧值,导致更新数据不正确。
解决方法
调用updateCase时动态传递最新的body配置,覆盖初始设置:
// 初始化updateCase时不指定body const { run: updateCase } = useFetchye(`${subApiUrl}/case/update`, { defer: true, credentials: 'include', headers: getDefaultHeaders(), method: 'POST', }); // 调用时传递最新的body const callUpdateCase = async () => { const { data } = await updateCase({ body: JSON.stringify(caseUpdateDtls) }); // ...后续逻辑 };
内容的提问来源于stack exchange,提问作者VoodooJellyfish
相关产品推荐
相关产品推荐

