首页 > 解决方案 > 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>
    );
};

上面的任何组件中是否有一些不寻常的东西会导致红人无限循环?

标签: javascriptreactjs

解决方案


据我所知:-

<MenuItem onClick={setOpenEditPopUp(true)}>Delete</MenuItem>

应该

<MenuItem onClick={handleClickEditOpen}>Delete</MenuItem>

解释:在每个渲染中,都会调用setOpenEditPopUp(true)而不是像您预期的那样将其绑定为事件处理程序。既然你已经handleClickEditOpen声明了,在这里重用它是有意义的。


推荐阅读