Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RichText: Memoize createRecord #11602

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions packages/editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,40 @@ export class RichText extends Component {
return { formats, text, start, end };
}

createRecord() {
/**
* Creates a new record from the current editable DOM.
*
* @param {Object} $1 Named arguments.
* @param {Object} $1.useCache Wether or not to use a cached record when the
* selection did not change. Recommended to use
* e.g. in the `selectionchange` event handler
* when nothing other than the selection could
* have changed.
*
* @return {Object} A new record.
*/
createRecord( { useCache } = {} ) {
const range = getSelection().getRangeAt( 0 );

return create( {
// If the range is shallowly equal to the last, return the last
// calculated value. This is useful when creating values on the
// `selectionchange` event, which fires more often than it should
// without a change in selection.
//
// Shallowly checking equality for ranges is fine:
//
// > Thus subsequent calls of this method returns the same range object
// > if nothing has removed the context object's range in the meantime.
// > In particular, getSelection().getRangeAt( 0 ) ===
// > getSelection().getRangeAt( 0 ) evaluates to true if the selection
// > is not empty.
// >
// > https://w3c.github.io/selection-api/#dom-selection-getrangeat
if ( useCache && range === this.createRecord.lastRange ) {
return this.createRecord.lastRecord;
}

const record = create( {
element: this.editableRef,
range,
multilineTag: this.multilineTag,
Expand All @@ -188,6 +218,11 @@ export class RichText extends Component {
filterString: ( string ) => string.replace( TINYMCE_ZWSP, '' ),
prepareEditableTree: this.props.prepareEditableTree,
} );

this.createRecord.lastRecord = record;
this.createRecord.lastRange = range;

return record;
}

applyRecord( record ) {
Expand Down Expand Up @@ -396,7 +431,7 @@ export class RichText extends Component {
return;
}

const { start, end, formats } = this.createRecord();
const { start, end, formats } = this.createRecord( { useCache: true } );

if ( start !== this.state.start || end !== this.state.end ) {
const isCaretWithinFormattedText = this.props.isCaretWithinFormattedText;
Expand Down