Scheduler Component Causing Can't perform a React state update on an unmounted component error

2 posts, 0 answers
  1. Howard
    Howard avatar
    5 posts
    Member since:
    Jun 2020

    Posted 10 Aug 2020 Link to this post

    So we are implementing the scheduler and are getting the following error:

    index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
        in KendoReactForm (created by SchedulerForm)
        in SchedulerForm (created by KendoReactSchedulerEditSlot)

    This error occurs after trying to close the edit event window provided when trying to add or edit an event on any day. We've commented out pretty much every piece of code that we wrote and left only the scheduler component in its most basic form. Cant seem to get rid of the error no matter what we tried.  The code is below, though i removed a few pieces of identifiable information:

     

    import React, {Component} from 'react';
    import { Scheduler, TimelineView, DayView, MonthView } from '@progress/kendo-react-scheduler';
    import { guid } from '@progress/kendo-react-common';
    import { Day } from '@progress/kendo-date-math';
    import axios from 'axios';


    export default class SchedulerComponent extends Component {
    constructor(props) {
    super(props);
    this._isMounted = false
    this.state = {
    // data: [{}],
    // loading: false,
    // hasError: false,
    // setData: null
    };
    // this.handleDataChange = this.handleDataChange.bind(this);
    }

    componentDidMount () {
    this._isMounted = true
    // this.setState({loading: true, mounted: true})
    // .then( ( response ) => {
    // this.setState( {
    // data: response.data,
    // loading: false
    // } )
    // console.log(this.state.data)
    // } )
    // .catch(err => {
    // this.setState( {
    // hasError: true,
    // loading: false
    // } )
    // } )

    }

    componentWillMount () {
    this._isMounted = false
    }

    // handleSubmit = event => {
    // event.preventDefault();

    // const dataupdate = {
    // data: this.state.data
    // };

    // axios.post('/post_scheduler_data', { dataupdate })
    // .then(res => {
    // console.log(res);
    // console.log(res.data);
    // })
    // }

    componentWillUnmount() {
    this._isMounted = false
    }

    handleSubmit = () => {
    this._isMounted && this.setState({ready: true})
    // const updateData = {
    // data: this.state.data
    // }
    // axios.post('/post_scheduler_data', updateData)
    // .then(response =>
    // console.log(response.data)
    // )
    // .catch(error => console.log(error));
    }

    handleDataChange = () => {
    this._isMounted && this.setState({ready: true})
    }

    // handleDataChange = ({ created, updated, deleted }) => {
    // setData = this.state.data
    // setData(old => old
    // // Filter the deleted items
    // .filter((item) => deleted.find(current => current.id === item.id) === undefined)
    // // Find and replace the updated items
    // .map((item) => updated.find(current => current.id === item.id) || item)
    // // Add the newly created items and assign an `id`.
    // .concat(created.map((item) => Object.assign({}, item, { id: guid() }))))
    // }





    render() {
    // const currentYear = new Date().getFullYear();
    // const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
    // const displayDate = new Date(Date.UTC(currentYear, 7, 24));
    //
    // const parseAdjust = (eventDate) => {
    // const date = new Date(eventDate);
    // date.setFullYear(currentYear);
    // return date;
    // }
    //
    // const customModelFields = {
    // id: 'TaskID',
    // title: 'Title',
    // description: 'Description',
    // start: 'Start',
    // end: 'End',
    // recurrenceRule: 'RecurrenceRule',
    // recurrenceId: 'RecurrenceID',
    // recurrenceExceptions: 'RecurrenceException',
    // category: 'Category'
    // };
    //
    // const sampleData = this.state.data.map(dataItem => (
    // {
    // id: dataItem.TaskID,
    // start: parseAdjust(dataItem.Start),
    // startTimezone: dataItem.startTimezone,
    // end: parseAdjust(dataItem.End),
    // endTimezone: dataItem.endTimezone,
    // isAllDay: dataItem.isAllDay,
    // title: dataItem.Title,
    // description: dataItem.Description,
    // recurrenceRule: dataItem.RecurrenceRule,
    // recurrenceId: dataItem.RecurrenceID,
    // recurrenceExceptions: dataItem.RecurrenceException,
    //
    // category: dataItem.category,
    // ownerID: dataItem.OwnerID,
    // personId: dataItem.OwnerID
    // }
    // ));
    //
    // const sampleDataWithResources = this.state.data.map(dataItem => (
    // {
    // id: dataItem.TaskID,
    // start: parseAdjust(dataItem.Start),
    // startTimezone: dataItem.startTimezone,
    // end: parseAdjust(dataItem.End),
    // endTimezone: dataItem.endTimezone,
    // isAllDay: dataItem.isAllDay,
    // title: dataItem.Title,
    // description: dataItem.Description,
    // recurrenceRule: dataItem.RecurrenceRule,
    // recurrenceId: dataItem.RecurrenceID,
    // recurrenceExceptions: dataItem.RecurrenceException,
    // roomId: randomInt(1, 2),
    // category: randomInt(1, 2),
    // }
    // ));
    //
    // const sampleDataWithCustomSchema = this.state.data.map(dataItem => (
    // {
    // ...dataItem,
    // Start: parseAdjust(dataItem.Start),
    // End: parseAdjust(dataItem.End),
    // PersonIDs: randomInt(1, 2),
    // Category: randomInt(1, 2),
    // }
    // ));
    //
    // const resources = [{
    // name: 'Meeting Type',
    // data: [
    // ],
    // field: 'category',
    // valueField: 'value',
    // textField: 'text',
    // colorField: 'color'
    // }]

    return(
    <Scheduler
    // resources={resources}
    // data={sampleData}
    // onDataChange={this.handleDataChange}
    editable={{
    add: true,
    // remove: true,
    // drag: true,
    // resize: true,
    // edit: true
    }}
    // defaultDate={displayDate}
    // defaultView="month"
    // onSubmit={this.handleSubmit}
    >
    {/*<MonthView */}
    {/* title="Month"*/}
    {/* selectedDateFormat="{0:M}"*/}
    {/* selectedShortDateFormat="{0:M}"*/}
    {/*/>*/}
    {/*<DayView numberOfDays={2}/>*/}
    {/*<TimelineView*/}

    {/* numberOfDays={2}*/}

    {/* columnWidth={75}*/}
    {/* slotDuration={60}*/}
    {/* slotDivisions={1}*/}

    {/* startTime={"08:00"}*/}
    {/* endTime={"18:00"}*/}

    {/* workDayStart={"08:00"}*/}
    {/* workDayEnd={"17:00"}*/}

    {/* workWeekStart={Day.Sunday}*/}
    {/* workWeekEnd={Day.Monday}*/}

    {/* showWorkHours={false} */}
    {/*/>*/}
    </Scheduler>

    )
    }
    }

  2. Stefan
    Admin
    Stefan avatar
    3034 posts

    Posted 11 Aug 2020 Link to this post

    Hello, Howard,

    I noticed that the same question is asked in a private ticket. 

    I will post the answer here as well, so more people can have access to it if they face the same issue:

    After investigating the warning on our side it appears that this is an issue with the Scheduler Editor and the way it registers the validators for the Form Field component. It invalidly use inline array which causes infinite loop as it's recreated on each rerender.

     
    
    // Incorrect multiple validators use
     <Field
          component={DatePicker}
          name={fields.start!}
          validator={[validators.required, validators.startAfterEnd]}
           timezone={startTimezone}
    />
     
    
     
    
    // Correct multiple validators use
    const startValidators = React.useMemo(
           () => [requiredValidator, startAfterEndValidator],
           [requiredValidator, startAfterEndValidator]
    );
    //....
    <Field
           component={DatePicker}
           name={fields.start!}
           validator={startValidators}
           timezone={startTimezone}
    />

    After fixing the issue on our side, the performance of the editor improved significantly. The fix will be released with next dev version, expected to be available to the end of the week.

    For reporting this issue I added you 1000 points which you can access from your account.

    Regards,
    Stefan
    Progress Telerik

Back to Top