@@ -65,6 +65,60 @@ type State = {
6565
6666let didInitODS = false ;
6767
68+ class UpdateEditorState extends React . Component < {
69+ editor : DraftEditor ,
70+ editorState : EditorState ,
71+ } > {
72+ render ( ) {
73+ return null ;
74+ }
75+ componentDidMount ( ) {
76+ this . _update ( ) ;
77+ }
78+ componentDidUpdate ( ) {
79+ this . _update ( ) ;
80+ }
81+ _update ( ) {
82+ if ( gkx ( 'draft_js_remove_componentwillupdate' ) ) {
83+ /**
84+ * Sometimes a render triggers a 'focus' or other event, and that will
85+ * schedule a second render pass.
86+ * In order to make sure the second render pass gets the latest editor
87+ * state, we update it here.
88+ * Example:
89+ * render #1
90+ * +
91+ * |
92+ * | cWU -> Nothing ... latestEditorState = STALE_STATE :(
93+ * |
94+ * | render -> this.props.editorState = FRESH_STATE
95+ * | + *and* set latestEditorState = FRESH_STATE
96+ * |
97+ * | |
98+ * | +--> triggers 'focus' event, calling 'handleFocus' with latestEditorState
99+ * | +
100+ * | |
101+ * +>cdU -> latestEditorState = FRESH_STATE | the 'handleFocus' call schedules render #2
102+ * | with latestEditorState, which is FRESH_STATE
103+ * |
104+ * render #2 <--------------------------------------+
105+ * +
106+ * |
107+ * | cwU -> nothing updates
108+ * |
109+ * | render -> this.props.editorState = FRESH_STATE which was passed in above
110+ * |
111+ * +>cdU fires and resets latestEditorState = FRESH_STATE
112+ * ---
113+ * Note that if we don't set latestEditorState in 'render' in the above
114+ * diagram, then STALE_STATE gets passed to render #2.
115+ */
116+ const editor = this . props . editor ;
117+ editor . _latestEditorState = this . props . editorState ;
118+ }
119+ }
120+ }
121+
68122/**
69123 * `DraftEditor` is the root editor component. It composes a `contentEditable`
70124 * div, and provides a wide variety of useful function props for managing the
@@ -237,43 +291,6 @@ class DraftEditor extends React.Component<DraftEditorProps, State> {
237291 }
238292
239293 render ( ) : React . Node {
240- if ( gkx ( 'draft_js_remove_componentwillupdate' ) ) {
241- /**
242- * Sometimes a render triggers a 'focus' or other event, and that will
243- * schedule a second render pass.
244- * In order to make sure the second render pass gets the latest editor
245- * state, we update it here.
246- * Example:
247- * render #1
248- * +
249- * |
250- * | cWU -> Nothing ... latestEditorState = STALE_STATE :(
251- * |
252- * | render -> this.props.editorState = FRESH_STATE
253- * | + *and* set latestEditorState = FRESH_STATE
254- * |
255- * | |
256- * | +--> triggers 'focus' event, calling 'handleFocus' with latestEditorState
257- * | +
258- * | |
259- * +>cdU -> latestEditorState = FRESH_STATE | the 'handleFocus' call schedules render #2
260- * | with latestEditorState, which is FRESH_STATE
261- * |
262- * render #2 <--------------------------------------+
263- * +
264- * |
265- * | cwU -> nothing updates
266- * |
267- * | render -> this.props.editorState = FRESH_STATE which was passed in above
268- * |
269- * +>cdU fires and resets latestEditorState = FRESH_STATE
270- * ---
271- * Note that if we don't set latestEditorState in 'render' in the above
272- * diagram, then STALE_STATE gets passed to render #2.
273- */
274-
275- this . _latestEditorState = this . props . editorState ;
276- }
277294 const {
278295 blockRenderMap,
279296 blockRendererFn,
@@ -381,6 +398,11 @@ class DraftEditor extends React.Component<DraftEditorProps, State> {
381398 style = { contentStyle }
382399 suppressContentEditableWarning
383400 tabIndex = { this . props . tabIndex } >
401+ { /*
402+ Needs to come earlier in the tree as a sibling (not ancestor) of
403+ all DraftEditorLeaf nodes so it's first in postorder traversal.
404+ */ }
405+ < UpdateEditorState editor = { this } editorState = { editorState } />
384406 < DraftEditorContents { ...editorContentsProps } />
385407 </ div >
386408 </ div >
0 commit comments