React使用useMemo包裹组件接收props时出现data未定义错误如何解决
问题成因
你错误混用了React.useMemo和组件定义的逻辑:
React.useMemo的第一个参数是无参的计算函数,返回要缓存的值,你在这里给这个计算函数加了({ data = [] })的形参,这个形参不会接收到父组件调用MemoDownloadsSubTab时传递的props,自然会出现data未定义的报错。- 同时你在JSX里直接把
useMemo返回的JSX片段当作组件调用,也不符合React语法规范。
修复方案
方案1:抽离子组件 + React.memo缓存(推荐)
把MemoDownloadsSubTab抽离到CorporateDetailsTable外部,用React.memo包裹实现props变化才重新渲染的缓存逻辑,是最规范的写法:
// 抽离到组件外部定义 const MemoDownloadsSubTab = React.memo(({ data = [] }) => { return ( <> {data?.length !== 0 && data?.map((row, rowIndex) => { return ( <Box key={rowIndex} bgcolor="mainDetailsCard.primary" m={1} p={1} borderRadius={5}> <Grid xs={12} item container spacing={2}> <Grid item xs={12} sm={3}> <Typography component="div"> <Box fontWeight="fontWeightBold" component="span" mr={1}> SRN : </Box> {row.SRN} </Typography> </Grid> <Grid item xs={12} sm={3}> <Typography component="div"> <Box fontWeight="fontWeightBold" component="span" mr={1}> Charge ID : </Box> {row.CHARGE_ID ? row.CHARGE_ID : "N/A"} </Typography> </Grid> </Grid> </Box> ); })} </> ); // 自定义对比逻辑,仅当charges变化时重新渲染,和你原有的依赖项逻辑一致 }, (prevProps, nextProps) => prevProps.data === nextProps.data); export const CorporateDetailsTable = ({ userHistorySummary, chargesCells, // 补全缺失的props接收 classes // 补全缺失的props接收 }) => { return ( <> {userHistorySummary?.masterData?.length !== 0 ? ( <Box mt={1}> <MemoDownloadsSubTab data={userHistorySummary?.charges} title={"Charges Registered"} cells={chargesCells} classes={classes} /> </Box> ) : ( <Typography variant="subtitle1" color="textSecondary"> No Data Available </Typography> )} </> ); };
方案2:保留内部定义,修正useMemo用法
如果一定要把逻辑写在CorporateDetailsTable内部,直接用useMemo缓存渲染结果即可,不需要定义成组件调用:
export const CorporateDetailsTable = ({ userHistorySummary, chargesCells, classes }) => { // 直接缓存渲染后的JSX片段 const memoDownloadsContent = React.useMemo(() => { const data = userHistorySummary?.charges || []; return ( <> {data?.length !== 0 && data?.map((row, rowIndex) => { return ( <Box key={rowIndex} bgcolor="mainDetailsCard.primary" m={1} p={1} borderRadius={5}> <Grid xs={12} item container spacing={2}> <Grid item xs={12} sm={3}> <Typography component="div"> <Box fontWeight="fontWeightBold" component="span" mr={1}> SRN : </Box> {row.SRN} </Typography> </Grid> <Grid item xs={12} sm={3}> <Typography component="div"> <Box fontWeight="fontWeightBold" component="span" mr={1}> Charge ID : </Box> {row.CHARGE_ID ? row.CHARGE_ID : "N/A"} </Typography> </Grid> </Grid> </Box> ); })} </> ); },[userHistorySummary?.charges]); return ( <> {userHistorySummary?.masterData?.length !== 0 ? ( <Box mt={1}> {/* 直接插入缓存的JSX即可,不需要当作组件调用 */} {memoDownloadsContent} </Box> ) : ( <Typography variant="subtitle1" color="textSecondary"> No Data Available </Typography> )} </> ); };
额外注意事项
- 你原代码中数组遍历没有加
key属性,要补上避免React触发警告 - 原代码return块中多写了冗余的
return (语法,需要删除 CorporateDetailsTable需要补全接收chargesCells、classes两个props,否则会触发未定义报错
内容的提问来源于stack exchange,提问作者user12302978
相关产品推荐
相关产品推荐

