3

我正在尝试使用 Full Calendar 和 Elastic Ui 构建一个日历应用程序,我使用状态来管理数据/事件输入,使用表单将事件添加到日历,并选择日历上的日期也会更新表单值。该应用程序现在部分工作,我可以将事件输入日历,但只有在我从日历中选择/单击日期之后,表格才能正常工作。但是,如果我在单击日历之前在表单中的文本字段或日期选择器上输入,则会出现以下错误并且整个页面变为空白。

超过最大更新深度。

上述错误发生在 DatePicker 组件中:

无法对未安装的组件执行 React 状态更新。

有人知道发生了什么吗?或者我怎样才能找到问题的根源?

webapp第一次加载时也有两个错误:

index.js:1 警告:无法在尚未安装的组件上调用 setState。这是一个无操作,但它可能表明您的应用程序中存在错误。相反,在 EuiIcon 组件中this.state直接分配或定义 state = {};具有所需状态的类属性。安慰。@

index.js:1 警告:无法在尚未安装的组件上调用 setState。这是一个无操作,但它可能表明您的应用程序中存在错误。相反,在 CalendarDataProvider 组件中直接分配 this.state或定义state = {};具有所需状态的类属性。

import React, { Component, useState } from 'react';
import FullCalendar from '@fullcalendar/react'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from "@fullcalendar/interaction"
import googleCalendarPlugin from '@fullcalendar/google-calendar'
import moment from 'moment'
import {EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiForm, EuiFormRow, EuiButton, EuiSwitch, 
EuiDatePicker, EuiDatePickerRange, EuiRadioGroup
} from '@elastic/eui'
require('dotenv').config()

const AddEventBar = (props) => {

const [isDisabled, setDisabled] = useState(false)
const [StartRepeatDate, setStartRepeatDate] = useState(null)
const [EndRepeatDate, setEndRepeatDate] = useState(null)
const [radioIdSelected, setRadioIdSelected] = useState(null);

const handleChangeStart = (date) => {
    setStartRepeatDate(date)
      }
    
const handleChangeEnd = (date) => {
    setEndRepeatDate(date)
      }

const radioHandler = (optionId) => {
    setRadioIdSelected(optionId);
};
    
const radios = [
{
    id: 'daily',
    label: 'daily',
},
{
    id: 'weekly',
    label: 'weekly',
},
];


return (
    <EuiFlexGroup>
        <EuiFlexItem> 
            <EuiForm>
                <EuiFormRow label='Event Title'>  
                    <EuiFieldText
                        onChange={props.titleHandler}
                        aria-label="Use aria labels when no actual label is in use"
                    />
                </EuiFormRow>
                <EuiFormRow label = 'Event Date'>
                    <EuiDatePicker
                        placeholder='Start'
                        selected={moment(props.start_date)}
                        onChange={props.startDatePickerHandler} 
                        aria-label="Start date"
                    />
                </EuiFormRow>
                <EuiFormRow label='Event Time'>
                    <EuiDatePickerRange 
                        startDateControl = { 
                        <EuiDatePicker
                                showTimeSelect
                                showTimeSelectOnly
                                selected={moment(props.start_date + ' ' + props.start_time)}
                                onChange={props.startDatePickerHandler}
                                timeFormat="hh:mm a"    
                                dateFormat="hh:mm a"
                            />}
                        endDateControl = {
                            <EuiDatePicker
                                showTimeSelect
                                showTimeSelectOnly
                                selected={moment(props.start_date + ' ' + props.end_time)}
                                onChange={props.endDatePickerHandler}
                                timeFormat="hh:mm a"
                                dateFormat="hh:mm a"
                            />
                        }
                    >
                    </EuiDatePickerRange>
                </EuiFormRow>
                <EuiFormRow>
                    <EuiSwitch
                        label="Repeat Event"
                        checked={isDisabled}
                        onChange={(e) => setDisabled(e.target.checked)}
                    />
                </EuiFormRow>
                <EuiFormRow>
                    <EuiDatePickerRange
                        startDateControl={
                        <EuiDatePicker
                            placeholder='Start'
                            disabled={!isDisabled}
                            selected={StartRepeatDate}
                            onChange={handleChangeStart}
                            startDate={StartRepeatDate}
                            endDate={EndRepeatDate}
                            isInvalid={StartRepeatDate > EndRepeatDate}
                            aria-label="Start date"
                        />
                        }
                        endDateControl={
                        <EuiDatePicker
                            placeholder='End'
                            disabled={!isDisabled}
                            selected={EndRepeatDate}
                            onChange={handleChangeEnd}
                            startDate={StartRepeatDate}
                            endDate={EndRepeatDate}
                            isInvalid={StartRepeatDate > EndRepeatDate}
                            aria-label="End date"
                        />
                        }
                    />
                </EuiFormRow>
                <EuiFormRow>
                <EuiRadioGroup
                    disabled={!isDisabled}
                    options={radios}
                    idSelected={radioIdSelected}
                    onChange={(id) => radioHandler(id)}
                    name="radio group"
                
                />
                </EuiFormRow>
                <EuiFormRow>
                    <EuiButton onClick={props.addEventHandler} type='submit'>
                        Add Event
                    </EuiButton>
                </EuiFormRow>
            </EuiForm>
        </EuiFlexItem>
    </EuiFlexGroup>
)
}

class Calendar extends Component {
    state = {
        selectInfo: null,
        // dateClickInfo: null,
        allDay: false,
        title: null,    
        start_date: moment(),
        end_date: moment(),
        start_time: null,
        end_time: null,
    }



addEventHandler = (state) => {
    if(this.state.title === null){
        alert('Please enter title')
    } 

    else if(this.state.selectInfo === null){
        alert('Please select event date')
    }
    
    else { 
        if(this.state.start_time || this.state.end_time){
            let calendarApi = this.state.selectInfo.view.calendar
                  calendarApi.addEvent({
                    title: this.state.title,
                    id: new Date(),
                    start: this.state.start_date.concat('T', this.state.start_time),
                    end: this.state.end_date.concat('T', this.state.end_time),
                  }) 
        } else {    
            let calendarApi = this.state.selectInfo.view.calendar
                calendarApi.addEvent({
                    title: this.state.title,
                    id: new Date(),
                    start: this.state.start_date,
                    end: this.state.end_date,
                    allDay: this.state.selectInfo.allDay,
                    })
        }
    }
}

titleHandler = (title) => {
    const titleValue = title.target.value
    this.setState({title: titleValue})
}

startDatePickerHandler = (date) => {
    // date is moment object
    const startDate = date.format().slice(0, 10)
    const startTime = date.format().slice(11, 16)
    // console.log('start date:' + startDate + ', start time:' + startTime)
    this.setState({start_date: startDate, start_time: startTime})
}

endDatePickerHandler = (date) => {
    // date is moment object
    const endDate = date.format().slice(0, 10)
    const endTime = date.format().slice(11, 16)
    // console.log('end date:' + endDate + ', end time:' + endTime)
    this.setState({end_date: endDate, end_time: endTime})
}

handleEventClick = (clickInfo) => {
    if (window.confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) {
    clickInfo.event.remove()
    }
}




handleDateSelect = (selectInfo) => {
    let calendarApi = selectInfo.view.calendar
    calendarApi.unselect() // clear date selection

    if(selectInfo) {
        if (selectInfo.startStr.length >= 10){
            const startStr = selectInfo.startStr.slice(0, 10)
            const endStr = selectInfo.endStr.slice(0, 10)
            const startTime = selectInfo.startStr.slice(11, 16)
            const endTime = selectInfo.endStr.slice(11, 16)
            this.setState({selectInfo: selectInfo, start_date: startStr, end_date: endStr, start_time: startTime, end_time: endTime})
    } else {
        this.setState({selectInfo: selectInfo, start_date:selectInfo.startStr, end_date: selectInfo.endStr})
    }
    }
}

render() {
    return (
    <EuiFlexGroup direction='row'>
        <EuiFlexItem grow={6}>
            <FullCalendar
            plugins={[ dayGridPlugin, interactionPlugin, timeGridPlugin, googleCalendarPlugin ]}
            googleCalendarApiKey = {process.env.REACT_APP_API_KEY}
            events = {{
                googleCalendarId: process.env.REACT_APP_GOOGLE_CALENDAR_ID
                }}
                headerToolbar={{
                    left: 'prev,next today',
                    center: 'title',
                    right: 'dayGridMonth,timeGridWeek,timeGridDay'
                }}
                initialView="dayGridMonth"
                selectable={true}
                editable={true}
                expandRows={true}
                select={this.handleDateSelect}
                // dateClick={dateClickHandler}
                eventClick={this.handleEventClick}
                />
        </EuiFlexItem>
        <EuiFlexItem grow={3}>
            <AddEventBar
                title={this.state.title}
                start_date={this.state.start_date}
                end_date={this.state.end_date}
                start_time={this.state.start_time}
                end_time={this.state.end_time}
                titleHandler={this.titleHandler}
                addEventHandler={this.addEventHandler}
                startDatePickerHandler={this.startDatePickerHandler}
                endDatePickerHandler={this.endDatePickerHandler}
            ></AddEventBar>
        </EuiFlexItem>
    </EuiFlexGroup>
    )
}}

export default Calendar
4

0 回答 0