首页 > 解决方案 > 如何防止反应组件中的无限循环?

问题描述

嗨,我是新来的反应,不幸的是我得到了这个代码的无限循环,我不知道为什么。这是有问题的代码:

if (projectInfo) {
        console.log('Length is', projectInfo.length);

        for (let i = 0; i < projectInfo.length; i++) {
            setValues({ ...values, fromDates: projectInfo[i].fromDate });
            console.log('i is', i);
        }
    }

整个组件在这里:

import React from 'react';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import Map from '../../shared/components/Map/Map';

export default function FieldworkInofrmation(props) {
    const projectInfo = props.props.fieldwork;

    const [values, setValues] = React.useState({
        fromDates: ' ',
    });

    if (projectInfo) {
        console.log('Length is', projectInfo.length);

        for (let i = 0; i < projectInfo.length; i++) {
            setValues({ ...values, fromDates: projectInfo[i].fromDate });
            console.log('i is', i);
        }
    }

    return (
        <Grid container spacing={3}>
            <Grid item xs={12}>
                <Box fontWeight="fontWeightBold" m={1}>
                    Fieldwork Information
                </Box>
            </Grid>
            <Grid item xs={12}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Click on map point to view details for the point
                </Box>
            </Grid>
            <Grid item xs={12}>
                <Map />
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Type:
                </Box>
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Period:
                </Box>
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    From:
                </Box>
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    To:
                </Box>
            </Grid>
            <Grid item xs={6}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Coordinates:
                </Box>
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Station:
                </Box>
            </Grid>
            <Grid item xs={1}>
                <Box fontWeight="fontWeightLight" m={1}>
                    Location:
                </Box>
            </Grid>
        </Grid>
    );
}

我尝试在 for 循环的末尾插入“i++”,但仍然出现错误:“重新渲染太多。React 限制了渲染的数量以防止无限循环”。我能做些什么来解决这个问题?

标签: javascriptreactjsfor-loopinfinite-loop

解决方案


正如其他人所提到的,您获得无限循环的原因是因为您在渲染期间更新了状态,这会导致重新渲染,从而再次更新状态,等等。

由于您要做的只是有效地设置初始状态,因此无需使用“setState”方法(或在您的情况下为“setValues”)。

只需执行以下操作:

const projectInfo = props.props.fieldwork;

const initialValues = {
    fromDates: ' ',
};

if (projectInfo) {
    for (let i = 0; i < projectInfo.length; i++) {
        initialValues = { ...initialValues, fromDates: projectInfo[i].fromDate };
    }
}

const [values, setValues] = React.useState(initialValues); 

但是,在您当前的实现中,您不断地覆盖“fromDates”的值。我怀疑这values应该是一个对象数组,每个对象都有自己的“fromDates”字段。例如:

const projectInfo = props.props.fieldwork;

const initialValues = [{
    fromDates: ' ',
}] // this is now an array

if (projectInfo) {
    for (let i = 0; i < projectInfo.length; i++) {
        initialValues.push({ fromDates: projectInfo[i].fromDate });
    }
}

const [values, setValues] = React.useState(initialValues); // `values` will now have an array of objects [{ fromDate: ' ' }, { fromDate: 'Oct 14th, 2019' }, ...]

最后,如果您确实打算覆盖“fromDate”并且您只关心最新值,则根本不需要循环。只需设置projectInfo数组中的最新值:

const projectInfo = props.props.fieldwork;

const initialValues = {
    fromDates: ' ',
};

if (projectInfo) {
    initialValues.fromDates = projectInfo[projectInfo.length -1].fromDates;
}

const [values, setValues] = React.useState(initialValues); 

@Ghojzilla 在评论中也提到了最后一个解决方案。


推荐阅读