Skip to content

Commit

Permalink
Fix modifying state during onChange triggered by beforeinput (faceboo…
Browse files Browse the repository at this point in the history
…karchive#667)

Fixes facebookarchive#92.

If an onChange handler replaces every "x" with an "abc", then when you type "x", we trigger onChange from beforeinput and rerender immediately with the content "abc", then the browser still inserts an "x" character!

This fix is surprisingly simple: instead of triggering an update during beforeinput, we simply wait until the input event to do so. This means that when we rerender, the browser would have already inserted the "x" character and React will correctly delete it when rerendering.

Test Plan: In plaintext example, change the handler to

```
this.onChange = (editorState) => {
  var content = editorState.getCurrentContent();
  return this.setState({
    editorState: EditorState.set(editorState, {
      currentContent: Modifier.removeInlineStyle(content, content.getSelectionAfter(), 'OVERFLOW');
    }),
  });
};
```

then type. Characters don't get duplicated like they did before.
  • Loading branch information
sophiebits authored and ouchxp committed Apr 7, 2017
1 parent fd48def commit 12d1d4a
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/component/base/DraftEditor.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class DraftEditor extends React.Component {
_editorKey: string;
_placeholderAccessibilityID: string;
_latestEditorState: EditorState;
_pendingStateFromBeforeInput: ?EditorState;

/**
* Define proxies that can route events to the current handler.
Expand Down
10 changes: 6 additions & 4 deletions src/component/handlers/edit/editOnBeforeInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,16 @@ function editOnBeforeInput(editor: DraftEditor, e: SyntheticInputEvent): void {
)
) {
e.preventDefault();
editor.update(newEditorState);
} else {
// The native event is allowed to occur.
newEditorState = EditorState.set(newEditorState, {
// The native event is allowed to occur. To allow user onChange handlers to
// change the inserted text, we wait until the text is actually inserted
// before we actually update our state. That way when we rerender, the text
// we see in the DOM will already have been inserted properly.
editor._pendingStateFromBeforeInput = EditorState.set(newEditorState, {
nativelyRenderedContent: newEditorState.getCurrentContent(),
});
}

editor.update(newEditorState);
}

module.exports = editOnBeforeInput;
5 changes: 5 additions & 0 deletions src/component/handlers/edit/editOnInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ var DOUBLE_NEWLINE = '\n\n';
* due to a spellcheck change, and we can incorporate it into our model.
*/
function editOnInput(editor: DraftEditor): void {
if (editor._pendingStateFromBeforeInput !== undefined) {
editor.update(editor._pendingStateFromBeforeInput);
editor._pendingStateFromBeforeInput = undefined;
}

var domSelection = global.getSelection();

var {anchorNode, isCollapsed} = domSelection;
Expand Down

0 comments on commit 12d1d4a

Please sign in to comment.