错误:我的模态组件超出了最大更新深度

时间:2020-09-18 13:23:00

标签: reactjs infinite-loop

错误:超出最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。 React限制了嵌套更新的数量,以防止无限循环。

当我的模态打开超过几秒钟时,出现上述错误。似乎是一个无限循环,但我找不到它。

const BookingsTable = ({data, setPage, parameters, setParameters, loading, setLoading}) => {
  const [modalOpen, setModalOpen] = useState(false);
  const [idLocation, setIdLocation]= useState('');
  const [mounted, setMounted] = useState(false);
  const [locationDetails, setLocationDetails] = useState('');

  const session = new SessionService();
  const { dataFromFetch, error } = useSWR([mounted ? `${session.domain}/external-booking/${idLocation}` : null, parameters ], url =>
      session.fetch(url, {
          method: 'POST',
          body: JSON.stringify({
              parametersToCheck: parameters
          })
      })
      , {
          onSuccess: (dataFromFetch) => {
            setLocationDetails(dataFromFetch)
            setModalOpen(true)
            setLoading(false)
            setMounted(false)
          },
          onError: (err, key, config) => {
            // console.log("error", err)
          }
      }
  )

  useEffect(() => {
    setMounted(true)
    setLoading(true)
    console.log('passed in useEffect')
  }, [idLocation])

  return (
    <Fragment>
      <CSSTransitionGroup component="div" transitionName="TabsAnimation" transitionAppear={true}
        transitionAppearTimeout={0} transitionEnter={false} transitionLeave={false}>
        <Row>
          <Col md="12">
            <Card className="main-card mb-3">
              <CardBody>

                <ReactTable data={data.data}
                  columns={[
                    {
                      Header: "Réservation",
                      columns: [
                        {
                          Header: "Numéro",
                          id: 'booking_id',
                          maxWidth: 80,
                          accessor: (d) => d.booking.id,
                        },
                        {
                          Header: "Locataire",
                          id: 'tenant_name',
                          sortable: false,
                          accessor: (d) => d.booking.user ? d.booking.user.last_name + ' ' + d.booking.user.first_name : ''
                        },
                        {
                          Header: "Début",
                          id: 'start_date',
                          accessor: (d) => format(new Date(d.booking.start_date), "dd/MM/yyyy à hh'h'mm"),
                        }
                        ,
                        {
                          Header: "Fin",
                          id: 'end_date',
                          accessor: (d) => format(new Date(d.booking.end_date), "dd/MM/yyyy à hh'h'mm"),
                        }
                      ],
                    },
                    {
                      Header: "Véhicule",
                      columns: [
                        {
                          Header: "Immat.",
                          id: 'vehicle_registration_number',
                          accessor: (d) => d.booking.vehicle.registration_number,
                        },
                        {
                          Header: "Modèle",
                          id: 'vehicle_model',
                          accessor: (d) => d.booking.vehicle.brand + ' ' + d.booking.vehicle.model,
                          sortable: false
                        },
                        {
                          Header: "Cat.",
                          id: 'vehicle_category',
                          accessor: (d) => d.booking.vehicle.zc_category ? d.booking.vehicle.zc_category.name : '',
                        },
                      ],
                    },
                    {
                      Header: "Informations",
                      columns: [
                        {
                          Header: "Créée le",
                          id: 'created_at',
                          accessor: (d) => format(new Date(d.booking.created_at), "dd/MM/yyyy"),
                        },
                        {
                          Header: "Statut",
                          id: "booking_status",
                          accessor: (d) => d.booking.status,
                          Cell: (row) => (
                              <span>
                                <span
                                  style={{
                                    color:
                                      row.value < 30
                                        ? "#aaa"
                                        : row.value >= 30 && row.value <= 60
                                        ? "#3ac47d"
                                        : row.value >= 70 && row.value <= 100
                                        ? "#76C0DB"
                                        : row.value == 120 || row.value == 130
                                        ? `#fd7e14`
                                        : "#d92550",
                                    transition: "all .3s ease",
                                  }}>
                                  &#x25cf;
                                </span>{" "}
                                {row.value == 10
                                  ? "créée"
                                  : row.value >= 20 && row.value < 30
                                  ? `en attente de paiement`
                                  : row.value == 30
                                  ? `confirmée`
                                  : row.value > 30 && row.value <= 60
                                  ? `en cours`
                                  : row.value > 60 && row.value <= 100
                                  ? `terminée`
                                  : row.value == 110
                                  ? `refusée`
                                  : row.value == 120 || row.value == 130
                                  ? `expirée`
                                  : row.value > 130
                                  ? `annulée`
                                  : '-'}
                              </span>
                            ),
                        }
                      ]
                    }
                  ]}
                  defaultPageSize={20}
                  manual
                  loading={loading}
                  loadingText="Chargement..."
                  nextText="Suivant"
                  previousText="Précédent"
                  noDataText="Aucune données correspondantes"
                  showPageSizeOptions={false}
                  pages={data.numberPage}
                  onFetchData={(state, instance) => {
                    setLoading(true);
                    const params = {...parameters,
                      sort_by: state.sorted.length ? state.sorted[0].id + (state.sorted[0].desc ? '_desc' : '_asc') : 'id_desc' 
                    }
                    console.log("onFetchData", state.page, state.filtered, state.sorted, instance);
                    console.log("parameters", params);
                    setPage(state.page);
                    setParameters(params);
                  }}
                  className="-striped -highlight"
                  getTdProps={(state, rowInfo, column, instance) => {
                    return {
                      style: {
                        fontSize: '12px'
                      },
                      onClick: (e) => {
                        console.log('A Td Element was clicked!')
                        console.log('it produced this event:', e)
                        console.log('It was in this column:', column)
                        console.log('It was in this row:', rowInfo)
                        console.log('It was in this table instance:', instance)
                        // Router.push(`/bookings/${rowInfo.original.booking.id}`)
                        setLoading(true)
                        setIdLocation(rowInfo.original.booking.id)
                      }
                    }
                  }}
                />
              </CardBody>
            </Card>
          </Col>
        </Row>
      </CSSTransitionGroup>
      {loading? null : <ModifyLocationModal locationDetails={locationDetails} isOpen={modalOpen}/>}
      
      
    </Fragment>
  );
}

export default BookingsTable

我的模态成分是:

export default function SimpleModal(props) {

  const {isOpen, locationDetails} = props;
  const materialClasses = useStyles();
  const [open, setOpen] = useState(false);

  const handleOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  useEffect(() => {
    setOpen(isOpen)
  }, [isOpen])

  const body = (
    <div className={materialClasses.paper}>
        <HeaderOfModal handleClose={handleClose}/>
        <LocationDetails locationDetails={locationDetails} handleChange={props.handleChange} close={handleClose}/>
    </div>
  );

  return (
    <div>
      <div onClick={handleOpen}>
        {props.button}
      </div>
      <Modal
        open={open}
        onClose={handleClose}
        aria-labelledby="simple-modal-title"
        aria-describedby="simple-modal-description"
      >
        {body}
      </Modal>
    </div>
  );
}

似乎触发问题的我的模态主体是:

const LocationDetails = (props) => {

    const { locationDetails } = props;
    const date = new Date();
    const session = new SessionService();
    const company_id = localStorage.getItem('company_id')
    const { formData, error } = useSWR([`${session.domain}/company/${company_id}}/external-booking-form-data`, parameters ], url =>
        session.fetch(url, {
            method: 'GET',
        })
        , {
            onSuccess: (formData) => {
                setCategoryAndAgencies(formData)
                setLoading(false)
            },
            onError: (err, key, config) => {
                console.log("error", err)
            }
        }
    )


    console.log(locationDetails)
    const[ loading, setLoading] = useState(true);
    const [categoryAndAgencies, setCategoryAndAgencies] = useState('');
    const [parameters, setParameters] = useState('')
    const [state, setState] = useState({
        reference: locationDetails? locationDetails.data.external_booking.reference : '',
        source: locationDetails? locationDetails.data.external_booking.source : 'Site Web',
        statut: locationDetails? locationDetails.data.external_booking.status :'30',
        startingAgency: locationDetails? locationDetails.data.external_booking.start_agency :'5',
        endingAgency: locationDetails? locationDetails.data.external_booking.end_agency :'5',
        category: locationDetails? locationDetails.data.external_booking.vehicle_category.id :'23',
        vehicle: locationDetails? locationDetails.data.external_booking.vehicle.registration_number :'',
        totalPrice: locationDetails? locationDetails.data.external_booking.amount :'',
        paidPrice: locationDetails? locationDetails.data.external_booking.paid_amount :'',
        suppOptions: locationDetails? locationDetails.data.external_booking.options :'',
        driver: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].name : '',
        phone: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].phone_number :'',
        licence: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].driver_licence_number : '',
        countryDelivery: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].driver_licence_country : 'FR',
    })
    const [ dates, setDates ] = useState({
        startDate: locationDetails? locationDetails.data.external_booking.start_date : new Date(),
        endDate: locationDetails? locationDetails.data.external_booking.end_date : new Date(),
        obtainedDate: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].driver_licence_date : new Date(),
        birthDate: locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].birthday : date.setFullYear( date.getFullYear() - 21 ),
    })

    const handleChange = (e) => {
        const { value } = event.target
        setState({
            ...state,
            [event.target.name] : value
        })
    }

    const handleChangeDate = (name, date) => {
        setDates({
            ...dates,
            [name]: date
        })
    }

    const handleModification = () => {

    }

    return (
        <>
        {loading ? 
            <Loader className={classes.Loader} color="#ffffff" active type="ball-triangle-path" />
        : <div className={classes.LocationDetails}>
            <h5>Détails de la location</h5>
            <Form>
                <div className={classes.FirstLine}>
                <FormGroup className={classes.Reference}>
                    <Label className={classes.Label} for="reference">Référence</Label>
                    <Input
                        type="text"
                        name="reference"
                        id="reference"
                        placeholder="Référence de la location"
                        className={classes.Input}
                        onChange={handleChange}
                        value={locationDetails? locationDetails.data.external_booking.reference : state.reference}
                    />
                </FormGroup>
                <FormGroup className={classes.Source}>
                    <Label className={classes.Label} for="source">Source</Label>
                    <Input
                        type="select"
                        name="source"
                        id="source"
                        className={classes.Input}
                        onChange={handleChange}
                        value={locationDetails? locationDetails.data.external_booking.source : state.source}
                    >
                        <option>Site Web</option>
                        <option>Téléphone</option>
                        <option>Direct en agence</option>
                        <option>Broker</option>
                        <option>Autre</option>
                    </Input>
                </FormGroup>
                <FormGroup className={classes.Statut}>
                    <Label className={classes.Label} for="statut">Statut</Label>
                    <Input
                        type="select"
                        name="statut"
                        id="statut"
                        className={classes.Input}
                        onChange={handleChange}
                        value={locationDetails? locationDetails.data.external_booking.status : state.statut}
                    >
                        <option value={30}>Confirmée</option>
                        <option value={60}>En cours</option>
                        <option value={100}>Terminée</option>
                        <option value={131}>Annulée par le pro</option>
                        <option value={132}>Annulée par le locataire</option>
                        <option value={20}>En attente de paiement</option>
                    </Input>
                </FormGroup>
                </div>
                <div className={classes.SecondLine}>
                    <div className={classes.StartingDate}>
                        <label className={classes.Label}>Date de début </label>
                        <DatePicker
                            className={classes.Input}
                            value={state.startingDate}
                            name="startingDate"
                            onChange={(date) => handleChangeDate('startDate', date)}
                            showTimeSelect
                            selected={dates.startDate}
                            value={locationDetails? locationDetails.data.external_booking.start_date : dates.startDate}
                            timeFormat="HH:mm"
                            locale='fr'
                            timeIntervals={15}
                            dateFormat="d MMMM, yyyy HH:mm"
                            timeCaption="Time"
                            inputStyle={{ textAlign: 'center' }}
                            popperModifiers={{
                                flip: {
                                    behavior: ["bottom"] // don't allow it to flip to be above
                                },
                                preventOverflow: {
                                    enabled: false // tell it not to try to stay within the view (this prevents the popper from covering the element you clicked)
                                },
                                hide: {
                                    enabled: false // turn off since needs preventOverflow to be enabled
                                }
                            }}
                        />
                    </div>
                    <div className={classes.EndingDate}>
                        <label className={classes.Label}>Date de fin </label>
                        <DatePicker
                            className={classes.Input}
                            value={state.startingDate}
                            name="startingDate"
                            onChange={(date) => handleChangeDate('endDate', date)}
                            showTimeSelect
                            selected={dates.endDate}
                            value={locationDetails? locationDetails.data.external_booking.end_date : dates.endDate}
                            timeFormat="HH:mm"
                            locale='fr'
                            timeIntervals={15}
                            dateFormat="d MMMM, yyyy HH:mm "
                            timeCaption="Time"
                            popperModifiers={{
                                flip: {
                                    behavior: ["bottom"] // don't allow it to flip to be above
                                },
                                preventOverflow: {
                                    enabled: false // tell it not to try to stay within the view (this prevents the popper from covering the element you clicked)
                                },
                                hide: {
                                    enabled: false // turn off since needs preventOverflow to be enabled
                                }
                            }}
                        />
                    </div>
                </div>
                <div className={classes.ThirdLine}>
                <FormGroup className={classes.StartingAgency}>
                        <Label className={classes.Label} for="startingAgency">Agence de début</Label>
                        <Input
                            type="select"
                            name="startingAgency"
                            id="startingAgency"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.start_agency : state.startingAgency}
                        >
                            {categoryAndAgencies.data.form_data.agencies.map((element, index) => {
                                return <option key={index} value={element.id}>{element.name} - {element.code}</option>
                            })}
                        </Input>
                    </FormGroup>
                    <FormGroup className={classes.EndingAgency}>
                        <Label className={classes.Label} for="endingAgency">Agence de fin</Label>
                        <Input
                            type="select"
                            name="endingAgency"
                            id="endingAgency"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.end_agency : state.endingAgency}
                        >
                            {categoryAndAgencies.data.form_data.agencies.map((element, index) => {
                                return <option key={index} value={element.id}>{element.name} - {element.code}</option>
                            })}
                        </Input>
                    </FormGroup>
                </div>
                <div className={classes.FourthLine}>
                    <FormGroup className={classes.Category}>
                        <Label className={classes.Label} for="category">Catégorie</Label>
                        <Input
                            type="select"
                            name="category"
                            id="category"
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.vehicle_category.id :state.category}
                        >
                            {categoryAndAgencies.data.form_data.vehicle_categories.map((element, index) => {
                                return <option key={index} value={element.id}>{element.display_name}</option>
                            })}
                        </Input>
                    </FormGroup>
                    <FormGroup className={classes.Vehicle}>
                        <Label className={classes.Label} for="vehicle">Véhicule</Label>
                        <Input
                            type="text"
                            name="vehicle"
                            id="vehicle"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.vehicle.registration_number : state.vehicle}
                        />
                    </FormGroup>
                </div>
                <div className={classes.FifthLine}>
                    <FormGroup className={classes.TotalPrice}>
                        <Label className={classes.Label} for="totalPrice">Prix total</Label>
                        <Input
                            type="text"
                            name="totalPrice"
                            id="totalPrice"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={ locationDetails? locationDetails.data.external_booking.amount : state.totalPrice}
                        />
                    </FormGroup>
                    <FormGroup className={classes.PaidPrice}>
                        <Label className={classes.Label} for="paidPrice">Somme payée</Label>
                        <Input
                            type="text"
                            name="paidPrice"
                            id="paidPrice"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.paid_amount : state.paidPrice}
                        />
                    </FormGroup>
                    <FormGroup className={classes.SuppOptions}>
                        <Label className={classes.Label} for="suppOptions">Options supplémentaires</Label>
                        <Input
                            type="select"
                            name="suppOptions"
                            id="suppOptions"
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails? locationDetails.data.external_booking.options : state.suppOptions}
                        >
                            <option>Options</option>
                            <option>2</option>
                            <option>3</option>
                            <option>4</option>
                            <option>5</option>
                        </Input>
                    </FormGroup>
                </div>
                <h5>Conducteur principal</h5>
                <div className={classes.SixthLine}>
                    <FormGroup className={classes.Driver}>
                        <Label className={classes.Label} for="driver">Conducteur</Label>
                        <Input
                            type="text"
                            name="driver"
                            id="driver"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={locationDetails && locationDetails.data.external_booking.drivers[0] ? locationDetails.data.external_booking.drivers[0].name :state.driver}
                        />
                    </FormGroup>
                    <FormGroup className={classes.Phone}>
                        <Label className={classes.Label} for="phone">Téléphone</Label>
                        <Input
                            type="text"
                            name="phone"
                            id="phone"
                            placeholder=""
                            className={classes.Input}
                            onChange={handleChange}
                            value={state.phone}
                        />
                    </FormGroup>
                    
                    
                </div>
                <hr />
                <div className={classes.BtnContainer}>
                    <div className={classes.Btn} onClick={handleModification}>Enregistrer</div>
                </div>
            </Form>
            
            
        </div>}
        </>
    )
}

export default LocationDetails;

1 个答案:

答案 0 :(得分:0)

问题是在react datepicker中设置一个没有新日期的日期。由于某种原因,它会加载无限循环。