Skip to content

Commit

Permalink
Move _latestEditorState assignment back to commit phase
Browse files Browse the repository at this point in the history
Summary: Follow-up to D6994261. I believe this is more correct even though it is kind of a hacky approach.

Reviewed By: flarnie

Differential Revision: D7014753

fbshipit-source-id: 6107352ddbe5a90fa3235aae513a3c5b17574c55
  • Loading branch information
sophiebits authored and facebook-github-bot committed Feb 17, 2018
1 parent 584d849 commit 04c2b9c
Showing 1 changed file with 59 additions and 37 deletions.
96 changes: 59 additions & 37 deletions src/component/base/DraftEditor.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,60 @@ type State = {

let didInitODS = false;

class UpdateEditorState extends React.Component<{
editor: DraftEditor,
editorState: EditorState,
}> {
render() {
return null;
}
componentDidMount() {
this._update();
}
componentDidUpdate() {
this._update();
}
_update() {
if (gkx('draft_js_remove_componentwillupdate')) {
/**
* Sometimes a render triggers a 'focus' or other event, and that will
* schedule a second render pass.
* In order to make sure the second render pass gets the latest editor
* state, we update it here.
* Example:
* render #1
* +
* |
* | cWU -> Nothing ... latestEditorState = STALE_STATE :(
* |
* | render -> this.props.editorState = FRESH_STATE
* | + *and* set latestEditorState = FRESH_STATE
* |
* | |
* | +--> triggers 'focus' event, calling 'handleFocus' with latestEditorState
* | +
* | |
* +>cdU -> latestEditorState = FRESH_STATE | the 'handleFocus' call schedules render #2
* | with latestEditorState, which is FRESH_STATE
* |
* render #2 <--------------------------------------+
* +
* |
* | cwU -> nothing updates
* |
* | render -> this.props.editorState = FRESH_STATE which was passed in above
* |
* +>cdU fires and resets latestEditorState = FRESH_STATE
* ---
* Note that if we don't set latestEditorState in 'render' in the above
* diagram, then STALE_STATE gets passed to render #2.
*/
const editor = this.props.editor;
editor._latestEditorState = this.props.editorState;
}
}
}

/**
* `DraftEditor` is the root editor component. It composes a `contentEditable`
* div, and provides a wide variety of useful function props for managing the
Expand Down Expand Up @@ -237,43 +291,6 @@ class DraftEditor extends React.Component<DraftEditorProps, State> {
}

render(): React.Node {
if (gkx('draft_js_remove_componentwillupdate')) {
/**
* Sometimes a render triggers a 'focus' or other event, and that will
* schedule a second render pass.
* In order to make sure the second render pass gets the latest editor
* state, we update it here.
* Example:
* render #1
* +
* |
* | cWU -> Nothing ... latestEditorState = STALE_STATE :(
* |
* | render -> this.props.editorState = FRESH_STATE
* | + *and* set latestEditorState = FRESH_STATE
* |
* | |
* | +--> triggers 'focus' event, calling 'handleFocus' with latestEditorState
* | +
* | |
* +>cdU -> latestEditorState = FRESH_STATE | the 'handleFocus' call schedules render #2
* | with latestEditorState, which is FRESH_STATE
* |
* render #2 <--------------------------------------+
* +
* |
* | cwU -> nothing updates
* |
* | render -> this.props.editorState = FRESH_STATE which was passed in above
* |
* +>cdU fires and resets latestEditorState = FRESH_STATE
* ---
* Note that if we don't set latestEditorState in 'render' in the above
* diagram, then STALE_STATE gets passed to render #2.
*/

this._latestEditorState = this.props.editorState;
}
const {
blockRenderMap,
blockRendererFn,
Expand Down Expand Up @@ -381,6 +398,11 @@ class DraftEditor extends React.Component<DraftEditorProps, State> {
style={contentStyle}
suppressContentEditableWarning
tabIndex={this.props.tabIndex}>
{/*
Needs to come earlier in the tree as a sibling (not ancestor) of
all DraftEditorLeaf nodes so it's first in postorder traversal.
*/}
<UpdateEditorState editor={this} editorState={editorState} />
<DraftEditorContents {...editorContentsProps} />
</div>
</div>
Expand Down

0 comments on commit 04c2b9c

Please sign in to comment.