Only First Element Draggable; Uncaught TypeError: Cannot read property 'left' of undefined at _class.animateNodes at _this.handleSortMove
See original GitHub issueHi!
I love how these components work, but now that I’m trying to integrate react-sortable-hoc
into my app with my custom components, I’m having issues.
None of the elements in my list are draggable, except for the first one. When I start dragging that element (in fact when I first click it), I see a javascript error in the console:
Uncaught TypeError: Cannot read property 'left' of undefined
at _class.animateNodes (index.js:593)
at _this.handleSortMove (index.js:272)
I stepped into the debugger, and discovered that the method _this.getEdgeOffset(node);
is returning undefined. I noticed that this function is recursively calling itself many, many times, because node.parentNode !== this.container. The function getEdgeOffset calls itself for every element all the way up to body, html, and document, until it assigns undefined to _this.offsetEdge. I’m not sure if this is the cause, or related in some way, or just a red herring.
Are my components somehow in the wrong order? Is this related to the “Unknown” component I see in the react debugger?
Any help would be greatly appreciated.
Here’s a bit of my code (too much to paste it all in). Note that <Topic>
and <TopicSection>
are just presentational components which have several DOM elements wrapped in a parent <div> element.
const SortableTopic = SortableElement((props) => {
return (
<Topic
{...props}
/>
);
});
const SortableTopicSection = SortableElement((props) => {
return (
<TopicSection
{...props}
/>
);
});
const SortableList = SortableContainer(({
items,
onToggleSection,
onChangeSectionName,
onSaveSectionName,
onEditSectionName,
onDeleteSection,
onToggleAllTopics,
onAddNewTopic,
onDragSection,
collapsedSection,
collapsedAllTopics,
editMode,
tempSectionName,
editingSectionName,
collapsedDetails,
onToggleDetails,
collapsedTopic,
onToggleTopic,
onDragTopic,
onDeleteTopic,
}) => {
let lastDivider = '';
return (
items.map( (item, idx) => {
switch( item.type ) {
case 'divider':
// don't render sections that have been deleted
if('deleted' in item && item.deleted === 1) {
return '';
}
lastDivider = item.linkid;
return (
<SortableTopicSection
onToggleSection={onToggleSection}
onChangeSectionName={onChangeSectionName}
onSaveSectionName={onSaveSectionName}
onEditSectionName={onEditSectionName}
onDeleteSection={onDeleteSection}
onToggleAllTopics={onToggleAllTopics}
onAddNewTopic={onAddNewTopic}
onDragSection={onDragSection}
collapsedSection={collapsedSection}
collapsedAllTopics={collapsedAllTopics}
editMode={editMode}
tempSectionName={tempSectionName}
editingSectionName={editingSectionName}
section={item}
index={idx}
key={item.linkid}
/>
);
case 'topic':
if(!collapsedSection[lastDivider] && !('deleted' in item && item.deleted === 1)) {
return (
<SortableTopic
rootClassName='TopicPlan-topic'
topic={item}
collapsedDetails={collapsedDetails[item.uuid]}
onToggleDetails={onToggleDetails}
collapsedTopic={collapsedTopic[item.uuid]}
onToggleTopic={onToggleTopic}
placement='topicplan'
editPlanMode={editMode}
onDragTopicInPlan={onDragTopic}
onDeleteTopicFromPlan={onDeleteTopic}
index={idx}
key={item.uuid}
/>
);
} else {
return '';
}
default:
return (
<div>Error: unexpected item type: {item.type}</div>
);
}
}
)
...
...
const TopicPlan = ({
...
...
<section className='TopicPlanMainContent-container'>
<SortableList
items={items}
onToggleSection={onToggleSection}
onChangeSectionName={onChangeSectionName}
onSaveSectionName={onSaveSectionName}
onEditSectionName={onEditSectionName}
onDeleteSection={onDeleteSection}
onToggleAllTopics={onToggleAllTopics}
onAddNewTopic={onAddNewTopic}
onDragSection={onDragSection}
collapsedSection={collapsedSection}
collapsedAllTopics={collapsedAllTopics}
editMode={editMode}
tempSectionName={tempSectionName}
editingSectionName={editingSectionName}
collapsedDetails={collapsedDetails}
onToggleDetails={onToggleDetails}
collapsedTopic={collapsedTopic}
onToggleTopic={onToggleTopic}
onDragTopic={onDragTopic}
onDeleteTopic={onDeleteTopic}
onSortEnd={({oldIndex, newIndex}) => console.log('onSortEnd called', oldIndex, newIndex)}
/>
</section>
Issue Analytics
- State:
- Created 5 years ago
- Reactions:5
- Comments:12 (1 by maintainers)
Top GitHub Comments
Update: I discovered the answer to my question. It was necessary to have a DOM element between the
<SortableContainer>
HOC that gets injected and all of the<SortableItem>
HOCs that are within it. I wrapped a<div>
tag around the code{items.map((item, idx) => {
to resolve the issue. Great component - thank you @claudericDamn it! This should go into the docs!