Как предотвратить бесконечный цикл в компоненте реакции? - PullRequest
0 голосов
/ 14 октября 2019

Привет, я новичок, чтобы реагировать, и, к сожалению, я получаю бесконечный цикл с этим кодом, и я не уверен, почему. Это рассматриваемый код:

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>
    );
}

Я попытался вставить «i ++» в конце цикла for, но ошибка все равно получилась: "Слишком много повторных визуализаций. React ограничивает количество визуализаций, чтобы предотвратить бесконечный цикл". Что я мог сделать, чтобы решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 14 октября 2019

Как уже упоминали другие, причина того, что вы получаете бесконечный цикл, заключается в том, что вы обновляете состояние во время рендеринга, что вызывает повторный рендеринг, который снова обновляет состояние и т. Д.

Поскольку все, что вы пытаетесь сделать, это эффективно установить начальное состояние, нет необходимости использовать метод "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 в комментариях.

1 голос
/ 14 октября 2019

Это плохо, состояние обновляется каждый раз

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);
    }
}

Это хорошо, состояние обновляется один раз

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

до сих пор не уверен, зачем вам переопределять fromDates каждый раз

...