Skip to content

Commit aa97597

Browse files
committed
Fix editor regeneration and focus handling. Fix zenoamaro#593
1 parent f38b144 commit aa97597

File tree

1 file changed

+17
-20
lines changed

1 file changed

+17
-20
lines changed

src/index.tsx

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,9 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
209209
shouldComponentUpdate(nextProps: ReactQuillProps, nextState: ReactQuillState) {
210210
this.validateProps(nextProps);
211211

212-
// If no editor has been instantiated, the component should update
213-
if (!this.editor) return true;
214-
const editor = this.editor!;
215-
216-
// If the component has been regenerated, we already know we should update.
217-
if (this.state.generation !== nextState.generation) {
212+
// If the editor hasn't been instantiated yet, or the component has been
213+
// regenerated, we already know we should update.
214+
if (!this.editor || this.state.generation !== nextState.generation) {
218215
return true;
219216
}
220217

@@ -230,13 +227,13 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
230227
// NOTE: Comparing an HTML string and a Quill Delta will always trigger a
231228
// change, regardless of whether they represent the same document.
232229
if (!this.isEqualValue(nextContents, prevContents)) {
233-
this.setEditorContents(editor, nextContents);
230+
this.setEditorContents(this.editor, nextContents);
234231
}
235232
}
236233

237234
// Handle read-only changes in-place
238235
if (nextProps.readOnly !== this.props.readOnly) {
239-
this.setEditorReadOnly(editor, nextProps.readOnly!);
236+
this.setEditorReadOnly(this.editor, nextProps.readOnly!);
240237
}
241238

242239
// Clean and Dirty props require a render
@@ -262,16 +259,13 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
262259
}
263260

264261
componentDidUpdate(prevProps: ReactQuillProps, prevState: ReactQuillState) {
265-
if (!this.editor) return;
266-
const editor = this.editor;
267-
268262
// If we're changing one of the `dirtyProps`, the entire Quill Editor needs
269263
// to be re-instantiated. Regenerating the editor will cause the whole tree,
270264
// including the container, to be cleaned up and re-rendered from scratch.
271265
// Store the contents so they can be restored later.
272266
if (this.shouldComponentRegenerate(prevProps)) {
273-
const delta = editor.getContents();
274-
const selection = editor.getSelection();
267+
const delta = this.editor!.getContents();
268+
const selection = this.editor!.getSelection();
275269
this.regenerationSnapshot = {delta, selection};
276270
this.setState({generation: this.state.generation + 1});
277271
this.destroyEditor();
@@ -283,9 +277,8 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
283277
const {delta, selection} = this.regenerationSnapshot!;
284278
delete this.regenerationSnapshot;
285279
this.instantiateEditor();
286-
editor.setContents(delta);
287-
// NOTE: The editor will also set focus iff selection is non-null.
288-
if (selection) editor.setSelection(selection);
280+
this.editor!.setContents(delta);
281+
postpone(() => this.editor!.setSelection(selection!));
289282
}
290283
}
291284

@@ -390,16 +383,13 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
390383
*/
391384
setEditorContents(editor: Quill, value: Value) {
392385
this.value = value;
393-
const restoreFocus = editor.hasFocus();
394386
const sel = this.getEditorSelection();
395387
if (typeof value === 'string') {
396388
editor.setContents(editor.clipboard.convert(value));
397389
} else {
398390
editor.setContents(value);
399391
}
400-
if (restoreFocus) {
401-
Promise.resolve().then(() => this.setEditorSelection(editor, sel));
402-
}
392+
postpone(() => this.setEditorSelection(editor, sel));
403393
}
404394

405395
setEditorSelection(editor: Quill, range: Range) {
@@ -580,6 +570,13 @@ class ReactQuill extends React.Component<ReactQuillProps, ReactQuillState> {
580570
}
581571
}
582572

573+
/*
574+
Small helper to execute a function in the next micro-tick.
575+
*/
576+
function postpone(fn: (value: void) => void) {
577+
Promise.resolve().then(fn);
578+
}
579+
583580
// Compatibility Export to avoid `require(...).default` on CommonJS.
584581
// See: https://github.com/Microsoft/TypeScript/issues/2719
585582
export = ReactQuill;

0 commit comments

Comments
 (0)