[英]React - Error: Too many re-renders. React limits the number of renders to prevent an infinite loop
Been stuck on this error: Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
一直卡在这个错误上:
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
After debugging, I think I found the last culprit.经过调试,我想我找到了最后一个罪魁祸首。 It was to do with the next following components.
这与接下来的组件有关。 However I don't know why they are causing render issues.
但是我不知道为什么它们会导致渲染问题。
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} />
);
};
Here is the child: This is a loading component that basically shows a loading indicator, when the loading is done, then it displays the original Component
这是孩子:这是一个加载组件,基本上显示一个加载指示器,当加载完成时,它会显示原始
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;
Here is the component it loads.这是它加载的组件。 I'm pretty sure the error is somewhere here.
我很确定错误在这里的某个地方。 However I cant find it?
但是我找不到它?
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>
);
};
Is there something out of the ordinary in any of the components above that would cause infinite loop of redners?上面的任何组件中是否有一些不寻常的东西会导致红人无限循环?
From what I can infer:-据我所知:-
<MenuItem onClick={setOpenEditPopUp(true)}>Delete</MenuItem>
should be应该
<MenuItem onClick={handleClickEditOpen}>Delete</MenuItem>
Explanation: On each render there is invocation of setOpenEditPopUp(true)
rather than binding it as event handler as you expected it to be.说明:在每次渲染时都会调用
setOpenEditPopUp(true)
,而不是像您预期的那样将其绑定为事件处理程序。 Since you already have handleClickEditOpen
declared, reusing it here would make sense.由于您已经声明了
handleClickEditOpen
,因此在这里重用它是有意义的。
The error is probably in the following part of your code:错误可能在代码的以下部分:
<IconButton
style={{padding:0, marginTop:10}}
onClick={handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
Your onClick function is constantly being executed, and that is what´s the causing the re-renders.您的 onClick function 一直在执行,这就是导致重新渲染的原因。 Instead you need to pass it as a callback, so it will only execute when the user click on the button:
相反,您需要将它作为回调传递,因此它只会在用户单击按钮时执行:
<IconButton
style={{padding:0, marginTop:10}}
onClick={(index) => handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
There are other parts of the code in which the function is being called constantly, like here:代码的其他部分会不断调用 function,如下所示:
<MenuItem onClick={setOpenEditPopUp(true)}>Delete</MenuItem>
So remeber to replace them with callbacks.所以请记住用回调替换它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.