[REACT] [BUG] A huge extra "update" field is sent after rerender while using CRUD manager with Drag-from-Grid
We are using Bryntum with React, CRUD manager and with a side panel Grid of unscheduled events. We also have a logout / login feature implemented without page reload.
The steps to reproduce are the following:
-
Add Bryntum with CRUD manager and with a side panel Grid of unscheduled events
-
Open a page with the Scheduler displayed
-
Do something that doesn't reload the page but that unmounts and than mounts the Bryntum component. In our case, we would logout and log in back without reloading the page;
-
Drag an item from Grid to the main Schedule. There would be a sync request with data like { added: [item] };
-
Double click on that item at the Schedule to edit it, make some changes and save. There would be another sync request with data like { added: [item] } (instead of { updated: [item] } like normally).
-
Reload the page and see the same event present twice at the Scheduler.
When we mount the Scheduler component, we create a new scheduler config for it with a new CrudManager, and with new event stores. We even tried calling the "destroy" method on all of these objects before initializing new ones.
const initSchedulerConfig = () => {
const config = {
// ...
crudManager: initCrudManager(),
// ...
};
// ...
return config;
};
export const initCrudManager = () => {
resetBryntumStores();
const crudManager = new CrudManager({
eventStore,
resourceStore,
stores: [ unassignedEventStore ],
autoLoad: true,
autoSync: true,
transport: {
load: { url: 'our_load_endpoint_url' },
sync: { url: 'our_sync_endpoint_url' },
},
// ...
});
return crudManager;
};
const resetBryntumStores = () => {
resourceStore = initResourceStore();
eventStore = initEventStore();
unassignedEventStore = initUnassignedEventStore();
};
function initResourceStore() {
const nextEventStore = new ResourceStore({
id: 'resourceStore',
autoCommit: true,
});
return nextEventStore;
}
function initEventStore() {
const nextEventStore = new EventStore({
id: 'eventStore',
autoCommit: true,
writeAllFields: true,
});
return nextEventStore;
}
function initUnassignedEventStore() {
const nextUnassignedEventStore = new Store({
id: 'unassignedProjects',
syncDataOnLoad: true,
});
return nextUnassignedEventStore;
}
let resourceStore = initResourceStore();
let eventStore = initEventStore();
let unassignedEventStore = initUnassignedEventStore();
Scheduler component example:
const useSchedulerConfig = () => {
const [ schedulerConfig, setSchedulerConfig ] = useState(null);
useEffect(() => {
setSchedulerConfig(initSchedulerConfig());
}, []);
return schedulerConfig;
};
export const Scheduler = () => {
const [ scheduler, setScheduler ] = useState(null);
const schedulerConfig = useSchedulerConfig();
const setSchedulerRef = useCallback((bryntumScheduler) => {
if (bryntumScheduler !== null) {
const schedulerInstance = bryntumScheduler.instance;
setScheduler(schedulerInstance);
}
}, []);
if (schedulerConfig === null) return null;
return (
<>
<BryntumScheduler ref = { setSchedulerRef } { ...schedulerConfig } />
<Sidebar scheduler = { scheduler } />
</>
);
};
Sidebar component code example:
export const Sidebar = ({ scheduler }) => {
const gridRef = useCallback(
(node: UnassignedProjects) => {
if (node !== null) {
new Drag({
grid: node.unassignedGrid,
schedule: scheduler,
constrain: false,
outerElement: node.unassignedGrid?.element,
});
}
},
[ scheduler ],
);
return (
<>
<UnsheduledEvents ref = { gridRef } />
</>
);
};
UnsheduledEvents component code example:
export class UnsheduledEvents extends React.Component {
componentDidMount() {
this.unassignedGrid = new UnassignedGrid({
appendTo: 'unassignedContainer',
store: unassignedEventStore,
});
}
render() {
return <div id = 'unassignedContainer' />;
}
}
UnassignedGrid code example:
import { EventModel, Grid } from '@bryntum/scheduler';
export default class UnassignedGrid extends Grid {
static get $name() {
return 'UnassignedGrid';
}
static get defaultConfig() {
return {
// ...
store: {
modelClass: EventModel,
},
// ...
};
}
}