javascript - React - 错误:重新渲染太多。React 限制渲染次数以防止无限循环
问题描述
一直卡在这个错误上:Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
经过调试,我想我找到了最后一个罪魁祸首。这与接下来的组件有关。但是我不知道为什么它们会导致渲染问题。
export default function GetUserBuckets()
{
const ListLoading = LoadingComponent(UserBuckets);
const [appState, setAppState] = useState({
loading: true,
posts: null,
});
useEffect(() => {
if (!appState.loading) return;
axiosInstance.get('all/buckets/').then((res) => {
const allBuckets = res.data;
setAppState({ loading: false, buckets: allBuckets });
});
}, []);
return (
<ListLoading isLoading={appState.loading} buckets={appState.buckets} />
);
};
这是孩子:这是一个加载组件,基本上显示一个加载指示器,当加载完成时,它会显示原始Component
export function LoadingComponent(Component) {
return function LoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return (
<Container style={{justifyContent:"center",display:"flex", padding:"5rem"}} className="loadingCircle">
<CircularProgress />
</Container>
);
};
}
export default LoadingComponent;
这是它加载的组件。我很确定错误在这里的某个地方。但是我找不到它?
const UserBuckets = (props) => {
const { buckets } = props;
console.log(buckets[0].id)
const [openDeletePopUp, setOpenDeletePopUp] = useState(false);
const [bucketName, setBucketName] = useState('');
const [openEditPopUp, setOpenEditPopUp] = useState(false);
const [bucketId, setBucketId] = useState(null)
const randomStocks = Math.floor(Math.random() * buckets.stock_count);
const [anchorEl, setAnchorEl] = React.useState(null);
const [currentIndex, setCurrentIndex] = useState(0);
const theme = useTheme()
const classes = useStyles();
const handleClick = (index) => (event) => {
setAnchorEl(event.currentTarget);
setCurrentIndex(index);
};
const handleClickDeleteOpen = (bucket, id) => {
setOpenDeletePopUp(true);
setBucketName(bucket)
setBucketId(id)
};
const handleClickEditOpen = () => {
setOpenEditPopUp(true);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleDeleteClose = () => {
setOpenDeletePopUp(false);
};
console.log(buckets && buckets)
if (!buckets || buckets.length === 0) return <p>Can not find any buckets, make one below!</p>;
return (
<React.Fragment>
<Container style={{width:"90%"}} maxWidth="md" component="main">
<Grid container spacing={5} alignItems="stretch">
{buckets.map((bucket, index) =>
{
return (
<Grid item key={index} xs={12} sm={6} md={4} lg={4}>
<Card
className={classes.root}
style={{ height: "100%", borderRadius:"20px"}}
>
{(!bucket || bucket.stock_list === null) &&
<CardHeader className={classes.bucketTitle} classes={{ title: classes.bucketTitle }}
title={
<>
<Link
color="textPrimary"
href={'dash/' + bucket.slug}
className={classes.link}
style={{ textDecoration: 'none' }}
>
{bucket.name.substr(0, 50)}
</Link>
</>
}
subheader="Add Stocks to get started!"
action={
<>
<IconButton
style={{padding:0, marginTop:10}}
onClick={handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl) && index === currentIndex}
onClose={handleClose}
style={{boxShadow: 'none'}}
elevation={0}
>
<MenuItem onClick={handleClickDeleteOpen}>Edit </MenuItem>
<MenuItem onClick={setOpenEditPopUp(true)}>Delete</MenuItem>
</Menu>
</>
}
/>}
{bucket && bucket.stock_list != null &&
<CardHeader className="cardHeaderBucket"
title={
<>
<Link
color="textPrimary"
href={'dash/' + bucket.slug}
className={classes.link}
style={{ textDecoration: 'none', color: "white", margin:0 }}
>
{bucket.name.substr(0, 50)}
</Link>
</>}
action={
<>
<IconButton
style={{padding:0}}
onClick={handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl) && index === currentIndex}
onClose={handleClose}
>
<MenuItem onClick={function(event){ handleClickEditOpen(); handleClose()}}>Edit</MenuItem>
<MenuItem onClick={function(event){ handleClickDeleteOpen(bucket.name, bucket.id); handleClose()}}>Delete </MenuItem>
</Menu>
</>
}
style={{margin:0, textIndent:0}}
/>}
<CardContent className="cardContentBucket">
{(!bucket || bucket.bucket_pos_neg === null) &&
<p style={{ textAlign: "center" }} >
Your Bucket is empty...
</p>}
{bucket && bucket.bucket_pos_neg != null &&
<div className={classes.bucketText}>
<Grid container>
<Grid item xs={12} style={{marginTop:10}}>
{bucket.bucket_sectors.slice(0, 3)
.sort((a, b) => a.count > b.count)
.map((stock, index) =>
{return(
<Chip key={index} label={stock.sector} size="small" className="stockChips" />
)}
)}
<>
{(bucket.bucket_sectors.length > 3) &&
<Chip key={index} label={bucket.bucket_sectors.length - 3 +"+ more" } size="small" className="stockChips" />
}
</>
</Grid>
<Grid item>
<Grid item xs={12} sm={12}>
<Typography variant="overline" color="textSecondary">
{"Total Stocks: " + bucket.stock_count}
</Typography>
</Grid>
<Typography variant="overline" color="textSecondary">
Return Donut
</Typography>
</Grid>
<BucketDoughnutDisplay data={bucket.bucket_pos_neg} />
</Grid>
</div>
}
</CardContent>
</Card>
</Grid>
);
})}
</Grid>
</Container>
<DeleteBucketPopUp open={openDeletePopUp} handleClose={handleDeleteClose} bucket={bucketName} id={bucketId}/>
</React.Fragment>
);
};
上面的任何组件中是否有一些不寻常的东西会导致红人无限循环?
解决方案
据我所知:-
<MenuItem onClick={setOpenEditPopUp(true)}>Delete</MenuItem>
应该
<MenuItem onClick={handleClickEditOpen}>Delete</MenuItem>
解释:在每个渲染中,都会调用setOpenEditPopUp(true)
而不是像您预期的那样将其绑定为事件处理程序。既然你已经handleClickEditOpen
声明了,在这里重用它是有意义的。
推荐阅读
- python - Plotly 子图中的不同箱线图系列轨迹
- css - 我的汉堡菜单行不对齐怎么办
- php - 如何使用 swiftmailer-bundle 在 symfony 4 中设置多个邮件
- python - 类相互影响
- python - 将单个“for”循环转换为嵌套“for”循环
- javascript - 如果javascript中有活动的东西,你如何扫描
- processing - 如何确定点和圆之间的最短距离
- node.js - 在 NodeJs 中解码 base64 编码的 webm 视频
- azure - Application Insights 跳过事件
- python - 删除属于同一列表中另一个字符串子集的所有字符串