Draft-js: Bug - clearing editorState when blurred doesn't work

Created on 7 Jan 2017  Â·  6Comments  Â·  Source: facebook/draft-js

Hello, when I tried to use onBlur handler bellow, it doesn't work and I have no idea why. Otherwise editor works OK, I use the latest version.

Note that:

  • yes, the method runs after user blur from editor (and handleBlur is binded to this in contructor)
  • it also passes through my condition, so the actual code inside runs
  • it triggers another re-render of component after that, but the editorState is not changed
handleBlur() {
    const { resetTextOnBlur, text } = this.props;
    // reset editor to previous value in props
    if (resetTextOnBlur) {
      let editorState = EditorState.push(this.state.editorState, ContentState.createFromText(text));
      this.setState({ editorState });
    }
  }

render() {
    const { placeholder } = this.props;

    return (
      <Editor
        name="message"
        editorState={this.state.editorState}
        keyBindingFn={this.myKeyBindingFn}
        onChange={this.onChange}
        onBlur={this.handleBlur}
        ref="editor"
        placeholder={placeholder}
      />
    );
  }

Most helpful comment

Thank you very much guys! The solution is listen to getHasFocus() in onChange handler as @JohnONeill suggested. So this way, it works!

onChange(editorState) {
    const { resetTextOnBlur, text } = this.props;
    const focused = editorState.getSelection().getHasFocus();

    focused && this.setState({ editorState });

    if (resetTextOnBlur && !focused) {
      let newEditorState = EditorState.push(this.state.editorState, ContentState.createFromText(text));
      this.setState({ editorState: newEditorState });
    }
  }

All 6 comments

Ooh, changing
this.setState({ editorState });
to
this.setState({ editorState: editorState });
might help?

@JohnONeill Nope, it's just ES6 syntax. But thanks for trying.

Ah, bummer. Good to know about, though! 😅

Once you've created your new editorState, does the .getCurrentContent() look the way you'd expect it to? Maybe evaluate it there and at the beginning of render()? (Doesn't _seem_ like anything should be wrong – I'm clearly reaching for straws here... 😛)

I reproduced this issue in a fiddle:
https://jsfiddle.net/9xvLqgka/3/

As you can see in the console, draft calls onChange immediately after onBlur, which overwrites any change you made (your onChange handler replaces the editorState).

One solution (albeit hacky) is to use setTimeout to wait a frame before replacing the state. I made a fork of the fiddle, see line 30:
https://jsfiddle.net/7j05on19/

@calic39 Maybe you could just listen to the selection state's getHasFocus() – when it's false, you know the editor's blurred, and you can listen to that / restore the original text within your handleChange() handler:

https://jsfiddle.net/9xvLqgka/4/ (just added a line of logging around the selection state handleChange())

Thank you very much guys! The solution is listen to getHasFocus() in onChange handler as @JohnONeill suggested. So this way, it works!

onChange(editorState) {
    const { resetTextOnBlur, text } = this.props;
    const focused = editorState.getSelection().getHasFocus();

    focused && this.setState({ editorState });

    if (resetTextOnBlur && !focused) {
      let newEditorState = EditorState.push(this.state.editorState, ContentState.createFromText(text));
      this.setState({ editorState: newEditorState });
    }
  }
Was this page helpful?
0 / 5 - 0 ratings