Can't perform a React state update on an unmounted component with full calendar using elastic ui datepicker

731 views Asked by At

I am trying to build a calendar app with Full Calendar and Elastic Ui, I use state to manage data/event input, using form to add event to the calendar, and selecting the date on calendar also update the form value. The app is partly working now, I can input events to the calendar, but only after I select/click on the date from the calendar then the form would work fine. However if I input on the text field or date picker in the form before clicking on the calendar, the following error appear and the whole page turn blank.

Maximum update depth exceeded.

The above error occurred in the DatePicker component:

Can't perform a React state update on an unmounted component.

anyone have any idea what's happening? Or how can I find the root of the problem?

There are also two error when the webapp first loaded:

index.js:1 Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the EuiIcon component. console. @

index.js:1 Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the CalendarDataProvider component.

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
0

There are 0 answers