Draft-js: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Created on 4 Aug 2017  路  18Comments  路  Source: facebook/draft-js

The current behavior:

draftjs


macOS + Chrome 60

  • Select some text cross two lines
  • With IME to input some word
  • It will remove the node, and insert text, but got error

The same issues with #1089, but nobody care.

Most helpful comment

Hi everyone! On my project I completely get rid from next error "Failed to execute 'removeChild' on 'Node' with next solution
I hope it will help anyone who will face with the same problem.

import React from 'react';
import {Editor, EditorState, Modifier} from 'draft-js';

const HANDLED = 'handled';

class AwesomeFixEditor extends React.Component {

    state = {
        editorState: EditorState.createEmpty()
    };

    handleOnChange = editorState => this.setState({editorState});

    handleBeforeInput = (chars, editorState) => {
        const currentContentState = editorState.getCurrentContent();
        const selectionState = editorState.getSelection();

        this.handleOnChange(EditorState.push(
            editorState,
            Modifier.replaceText(
                currentContentState,
                selectionState,
                chars
            )
        ));

        return HANDLED;
    };

    render() {
        const {editorState} = this.state;

        return (
            <Editor
                editorState={editorState}
                handleBeforeInput={this.handleBeforeInput}
                onChange={this.handleOnChange} />
        );
    }
}

All 18 comments

This looks like a duplicate of #1301

Hi - just to get more info, what IME are you using? Is it an app or something that is part of MacOS? If so what version of macOS are you using?

@mmmoussa, @flarnie my os is macOS 10.12.5 and I use pinyin IME.

I found IME is the big question with React WYSIWYG Editor, not only draft-js. Maybe you can try to use pinyin IME to test.


I try to debugger the problem. I found that something wrong with composition events.

The onCompositionStart event will get the selection's text data, when keydown, the keydown event data will replace selection's data -- At this time, the DOM is removed. And then onCompositionEnd event will set current IME data into the target DOM -- At this time, it will throw the exception.


Others, Chrome's composition events is different with Firefox's composition events.

@mmmoussa @flarnie I need your help 馃啒

has this been solved yet?
i have similar issue with chinese character on draft js,
trying to create a custom hashtag decorator.

hashtag decorators not working after two or three chinese character subsequently.
and when I press backspace key to delete the node, Failed to execute 'removeChild' on 'Node';

but error only occurs on chrome.

Been getting reports of this specific "Failed to execute 'removeChild' on 'Node'" also specific to Mac + latest Chrome (69).

@octatone Did you gathered more insights into this? I'm experiencing the same issue with my draft.js editor.

I found the problem. The issue is related to an exception that's causing react to blow off and is not shown in the stack trace. In my case, it was related to font awesome (the js part of it) messing with the DOM and react not being able to reconcile properly.

I switched to an icon font that doesn't need JS at all. It's anyway a silly idea, I should have known better.

Hope this helps.

may this helps:
```js
getSelectedBlocks = () => {

const selectionState =this.state.editorState.getSelection()
const contentState = this.state.editorState.getCurrentContent()

const startKey = selectionState.getStartKey()
const endKey = selectionState.getEndKey()
const isSameBlock = startKey === endKey
const startingBlock = contentState.getBlockForKey(startKey)
const selectedBlocks = [startingBlock]

if (!isSameBlock) {
  let blockKey = startKey

  while (blockKey !== endKey) {
    const nextBlock = contentState.getBlockAfter(blockKey)
    selectedBlocks.push(nextBlock)
    blockKey = nextBlock.getKey()
  }
}

return selectedBlocks

}

handleCompositionStart = () => {

if (this.getSelectedBlocks().length > 1) {

  // if multi blocks in selection, remove selection range when composition start 
  const nextEditorState = EditorState.push(
    this.state.editorState,
    Modifier.removeRange( this.state.editorState.getCurrentContent(),  this.state.editorState.getSelection(), 'backward'),
    'remove-range'
  )

  this.setState({
    editorState: nextEditorState
  })

}

}
```

jsx <div onCompositionStart={this.handleCompositionStart}><Editor {/*....*/}/></div>

try to catch
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
// logErrorToMyService(error, info);
console.log('componentDidCatch:', this.getContent());
this.setState({
editorState: EditorState.createEmpty(draftDecorator)
});
}`

I found a simple solution, just add componentDidCatch method to your react component class:

class MyComponent extends Component {
    componentDidCatch() {
        this.forceUpdate();
    }

    render() {
        return <Editor .../>
    }
}

This can not fix the bug, but can prevent react component crash.

Hi everyone! On my project I completely get rid from next error "Failed to execute 'removeChild' on 'Node' with next solution
I hope it will help anyone who will face with the same problem.

import React from 'react';
import {Editor, EditorState, Modifier} from 'draft-js';

const HANDLED = 'handled';

class AwesomeFixEditor extends React.Component {

    state = {
        editorState: EditorState.createEmpty()
    };

    handleOnChange = editorState => this.setState({editorState});

    handleBeforeInput = (chars, editorState) => {
        const currentContentState = editorState.getCurrentContent();
        const selectionState = editorState.getSelection();

        this.handleOnChange(EditorState.push(
            editorState,
            Modifier.replaceText(
                currentContentState,
                selectionState,
                chars
            )
        ));

        return HANDLED;
    };

    render() {
        const {editorState} = this.state;

        return (
            <Editor
                editorState={editorState}
                handleBeforeInput={this.handleBeforeInput}
                onChange={this.handleOnChange} />
        );
    }
}

Hi everyone! On my project I completely get rid from next error "Failed to execute 'removeChild' on 'Node' with next solution
I hope it will help anyone who will face with the same problem.

import React from 'react';
import {Editor, EditorState, Modifier} from 'draft-js';

const HANDLED = 'handled';

class AwesomeFixEditor extends React.Component {

    state = {
        editorState: EditorState.createEmpty()
    };

    handleOnChange = editorState => this.setState({editorState});

    handleBeforeInput = (chars, editorState) => {
        const currentContentState = editorState.getCurrentContent();
        const selectionState = editorState.getSelection();

        this.handleOnChange(EditorState.push(
            editorState,
            Modifier.replaceText(
                currentContentState,
                selectionState,
                chars
            )
        ));

        return HANDLED;
    };

    render() {
        const {editorState} = this.state;

        return (
            <Editor
                editorState={editorState}
                handleBeforeInput={this.handleBeforeInput}
                onChange={this.handleOnChange} />
        );
    }
}

Using removes my toggled inline styles... how can i fix this?

@hjpunzalan I haven't tried this particular block of code, but replaceText accepts an optional 4th argument where you can put the inline style(s) to be retained: https://draftjs.org/docs/api-reference-modifier#replacetext
I think the styles have to be passed as an Immutable Map

@hjpunzalan Your solution is not working with mention plugin. Actually, when I start typing my suggestion for "@" and then backspace the suggested value, the screen will become blank for mobile-only but working on a laptop(Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.). Can you suggest how we can use resolve this?

I have the same issue @hjpunzalan @PulkitKoolKanya could you help me please

Someone knows the solution?

Was this page helpful?
0 / 5 - 0 ratings