react-sortable-hoc
react-sortable-hoc copied to clipboard
Cannot read property 'removeChild' of null
I used onMouseDown to delete items data, and I reported this error, unable to locate what the problem was.
<div
className='icon-close'
onMouseDown={this.onDelete.bind(this, value)}>
<Icon
type="close-circle"
className='icon-close' />
</div>
onDelete(value: string) {
console.log(value, 'value')
let { items } = this.state;
items = items!.filter((item: string) => item !== value);
this.setState({ items }, () => {
this.props.onDelete && this.props.onDelete(items);
})
}
Deleting will result in an error and a request will be sent. I don't know where the request originated and whether it can be blocked
I need help Thank you
I believe I may have run into a related issue after updating to the latest version of react-sortable-hoc
.
I was incorrectly calling React setState
in the SortableContainer
's onSortStart
callback. After reading the documentation it doesn't appear that calling setState
is supported in this context (I may not be correct about this).
I tried moving the setState
call to updateBeforeSortStart
instead, but started encountering some bizarre looking graphical bugs (the draggable item would appear like 600px away from it's correct position with ~50% opacity).
For my use case I was able to avoid calling setState
entirely, settling for a NOP instead of a new rendering. Not ideal, but it got things working ok.
I'm using the latest versions of react-sortable-hoc, invariant, react, and react-dom.
I have the exact same problem. I'm using the library with Redux and I'm getting the error even when not setting any state.
This is what my SortableList looks like (snippet of my component):
private getSortableList(jobs: Immutable.List<IJob>) {
const SortableItem = SortableElement(({ value, disabled }: { value: IJob; disabled: boolean }) => (
<Job job={value} key={value.get('jobId')} sortable={!disabled} />
));
const SortableList = SortableContainer(({ items }: { items: Immutable.List<IJob> }) => (
<div className='sortable-queue'>
{items.map((job, idx) => (
<SortableItem key={idx} index={idx} value={job} disabled={!this.isJobSortable(job)} />
))}
</div>
));
return (
<SortableList
items={jobs}
useDragHandle
key='sortableList'
onSortEnd={this.handleQueueOrderChange}
/>
);
}
private isJobSortable(job: IJob) {
const status = job.get('status');
return job.get('enqueued') && (status === 'idle' || status === 'error' || status === 'finished');
}
private handleQueueOrderChange({ newIndex, oldIndex }) {
console.log(newIndex, oldIndex);
}
I just had these same issues. It was caused by my SortableContainer and SortableElement being assigned inside of the render function. Meaning each time I set the state it would re-render and create a new instance of SortableContainer and SortableElement. That would divorce the old SortableElement from the DOM and cause the issues.
So the solution for me was to assign SortableContainer and SortableElement to variables outside of render() and reference those on render. Also, @rectangletangle is correct, updateBeforeSortStart should be used to set state rather that onSortStart.
@cpwinn could you share a code snippet of your solution? I'm not sure how else to assign the SortableContainer and SortableElement if they depend on props.
Good question @XeniaSiskaki. I passed my props and state from the top component down to SortableContainer and SortableElement as props like you already do with jobs
.
Here is a modified version of your snippet that illustrates that. Hopefully that helps.
private getSortableList(jobs: Immutable.List<IJob>) {
return (
<SortableList
items={jobs}
useDragHandle
key='sortableList'
onSortEnd={handleQueueOrderChange}
propA={props.propA}
propB={props.propB}
/>
);
}
const SortableList = SortableContainer(({ items, propA, propB }: { items: Immutable.List<IJob>; propA: any; propB: any }) => (
<div className='sortable-queue'>
{items.map((job, idx) => (
<SortableItem key={idx} index={idx} value={job} disabled={!isJobSortable(job)} propB={propB} />
))}
</div>
));
const SortableItem = SortableElement(({ value, disabled, propB }: { value: IJob; disabled: boolean; propB: any }) => (
<Job job={value} key={value.get('jobId')} sortable={!disabled} />
));
private isJobSortable(job: IJob) {
const status = job.get('status');
return job.get('enqueued') && (status === 'idle' || status === 'error' || status === 'finished');
}
private handleQueueOrderChange({ newIndex, oldIndex }) {
console.log(newIndex, oldIndex);
}
is there a specific reason why the code is not protected against this case, and it is protected in the unmount?
// Remove the helper from the DOM
this.helper.parentNode.removeChild(this.helper);
versus:
if (this.helper && this.helper.parentNode) {
this.helper.parentNode.removeChild(this.helper);
}
do you accept a PR to protect by this check in both cases?
I also have this problem which is very annoying:
const onSortStart = (): void => {
console.log('%c sort started!', 'color: green;');
setIsReorderingColumns((prevState) => !prevState);
};
Uncaught TypeError: Cannot read property 'removeChild' of null
I just had these same issues. It was caused by my SortableContainer and SortableElement being assigned inside of the render function. Meaning each time I set the state it would re-render and create a new instance of SortableContainer and SortableElement. That would divorce the old SortableElement from the DOM and cause the issues.
So the solution for me was to assign SortableContainer and SortableElement to variables outside of render() and reference those on render. Also, @rectangletangle is correct, updateBeforeSortStart should be used to set state rather that onSortStart.
Thanks, it solved my problem perfectly!
I just had these same issues. It was caused by my SortableContainer and SortableElement being assigned inside of the render function. Meaning each time I set the state it would re-render and create a new instance of SortableContainer and SortableElement. That would divorce the old SortableElement from the DOM and cause the issues.
So the solution for me was to assign SortableContainer and SortableElement to variables outside of render() and reference those on render. Also, @rectangletangle is correct, updateBeforeSortStart should be used to set state rather that onSortStart.
It also solved my problem! Thank you 🙌
I am having this problem with my onSortEnd call. I have SortableContainer and SortableElement outside of the render function as suggested above. I suppose I will fork the code and add a guard around the offending line as @bartvde suggested.