превышена глубина обновления при использовании массива полей формы - PullRequest
0 голосов
/ 24 февраля 2020

Я использую Redux Form Field Array, и при добавлении нового элемента в массив полей приложение вылетает из-за следующей ошибки:

Превышена максимальная глубина обновления. Это может произойти, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений для предотвращения бесконечных циклов.

Код компонента:

import React from 'react';
import {reduxForm, Field, FieldArray} from 'redux-form';

import { 
    Button,
    CircularProgress,
    Grid,
}from '@material-ui/core';
import {Link} from 'react-router-dom';
import { makeStyles } from '@material-ui/styles';

import {FileInput, SelectInput, LocationInput, TextInput } from './FormFields';
import { SERVICES } from '../Routing/routes';

const userStyles = makeStyles(theme=>({
    section:{
        maxWidth:theme.breakpoints.values.md,
        margin:'0 auto',

    },
    form:{
        position:'relative',
        paddingBottom:theme.spacing(8)
    },
    actionButtons:{
        position:'fixed',
        bottom:0,
        right:0,
        padding:theme.spacing(3),
        backgroundColor:theme.palette.secondary.main,
        borderTop: `1px solid ${theme.palette.primary.main}`
    },
    button:{
        marginLeft:theme.spacing(1)
    }
}));




const ProviderServiceForm = (props) =>{
    const classes = userStyles();
    const {handleSubmit, onFormSubmit, pending} = props;

    const renderSubmitIcon = () =>{
        if(pending)
            return <CircularProgress color="primary" size={20}/>
        else
            return  
    }

    const renderField = ({ input, label, type, meta: { touched, error } }) => (
        <div>
          <label>{label}</label>
          <div>
            <input {...input} type={type} placeholder={label} />
            {touched && error && <span>{error}</span>}
          </div>
        </div>
      );

    const renderVariants = ({ fields, meta: { error, submitFailed } }) =>(
        <ul>
            <li>
                <Button onClick={() => fields.push({})}>Añadir</Button>
                {submitFailed && error && <span>{error}</span>}
            </li>
            {fields.map((variant,index)=>(
                <li key={index}>
                    <h4>Variante #{index + 1}</h4>
                    <Field
                        name={`${variant}.title`}
                        type="text"
                        component={renderField}
                        label="First Name"
                    />
                </li>
            ))}
        </ul>
    );


    return(
        <div className={classes.section}>
            <form onSubmit={handleSubmit(onFormSubmit)} className={classes.form}>
                <input type="hidden" value="something"/>
                <FieldArray name="variants" component={renderVariants}/>
                <Field name="placeName" label="Nombre del centro o del lugar" component={TextInput} autoComplete="organization"/>
                <Field name="address" label="Dirección" component={LocationInput} autoComplete="off"/>
                <Field name="adressDetails" label="Planta, Piso, Puerta..." component={TextInput} autoComplete="address-level3"/>
                <Field name="category"  label="Categoría de servicios" component={SelectInput} autoComplete="category"/>
                <Field name="image" type="file" label="Sube una foto..." component={FileInput}/>
                <Grid container className={classes.actionButtons} justify="flex-end">
                    <Link to={SERVICES} style={{ textDecoration: 'none' }}>
                        <Button type="submit" variant="outlined" color="primary" disabled={pending}>Cancelar</Button>
                    </Link>
                    <Button type="submit" variant="contained" color="primary" className={classes.button} disabled={pending} startIcon={renderSubmitIcon()}>Guardar</Button>
                </Grid>
            </form>
        </div>
    )
}

const validate = (formValues) =>{
    const errors = {}

    if (!formValues.variants || !formValues.variants.length) {
        errors.variants = { _error: 'Almenos tienes que introducir una variante' };
      } else {
        const variantsArrayErrors = [];
        formValues.variants.forEach((variant, variantIndex) => {
          const variantErrors = {};
          if (!variant || !variant.title) {
            variantErrors.title = 'Tienes que introducir un título';
            variantsArrayErrors[variantIndex] = variantErrors;
          }
          if (!variant || !variant.price > 0) {
            variantErrors.price = 'Tienes que poner un precio superior a 0€';
            variantsArrayErrors[variantIndex] = variantErrors;
          }
        });
        if (variantsArrayErrors.length) {
            errors.variants = variantsArrayErrors;
        }
    }
    if (!formValues.placeName){
        errors.placeName = 'Debes intriducir el nombre del centro o lugar'
    }
    if (!formValues.address){
        errors.address = 'Debes intriducir una dirección válida'
    }
    if(!formValues.category){
        errors.category = 'Tienes que seleccionar una categoría';
    }
    if(!formValues.image){
        errors.image = 'Debes seleccionar una imagen de Portada';
    }

    return errors;
}


export default reduxForm({
    form:'ProviderServiceForm',
    validate,
})(ProviderServiceForm);

Я думаю, что ошибка возникает, когда я выполняю следующий код строки :

<Button onClick={() => fields.push({})}>Añadir</Button>

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

Я удивлен, так как большая часть кода Field Array была скопирована из документации избыточной формы :

https://redux-form.com/8.3.0/examples/fieldarrays/

Есть идеи, как это исправить?

Заранее спасибо.

1 Ответ

1 голос
/ 24 февраля 2020

эта часть кода неверна

onSubmit={handleSubmit(onFormSubmit)}

используйте вместо этого функцию стрелки, чтобы исправить проблему:

onSubmit={() => handleSubmit(onFormSubmit)}

, когда вы пишете функцию с () в функции рендеринга, при каждом отображении страницы функция будет вызывать и вызывать изменение состояния все больше и больше.

...