This is a migrated thread and some comments may be shown as answers.

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

1 Answer 249 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Howard
Top achievements
Rank 1
Veteran
Howard asked on 10 Aug 2020, 08:11 PM

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>

)
}
}

1 Answer, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 11 Aug 2020, 01:07 PM

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

Tags
General Discussions
Asked by
Howard
Top achievements
Rank 1
Veteran
Answers by
Stefan
Telerik team
Share this question
or