错误:超出最大更新深度。当组件重复调用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",
}}>
●
</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;
答案 0 :(得分:0)
问题是在react datepicker中设置一个没有新日期的日期。由于某种原因,它会加载无限循环。