Skip to content

Commit

Permalink
Fix RichText rerendering when it shouldn't
Browse files Browse the repository at this point in the history
The prepareEditableTree and onChangeEditableValue function stacks
would have a new reference on every render. This prevents that by
memoized the stack based on the previous stack and the newly added
function.
  • Loading branch information
atimmer committed Nov 21, 2018
1 parent 015e144 commit 254cf33
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 24 deletions.
55 changes: 41 additions & 14 deletions packages/annotations/src/format/annotation.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import memize from 'memize';

/**
* WordPress dependencies
*/
Expand Down Expand Up @@ -115,6 +120,40 @@ function updateAnnotationsWithPositions( annotations, positions, { removeAnnotat
} );
}

/**
* Create prepareEditableTree memoized based on the annotation props.
*
* @param {Object} The props with annotations in them.
*
* @return {Function} The prepareEditableTree.
*/
const createPrepareEditableTree = memize( ( props ) => {
const { annotations } = props;

return ( formats, text ) => {
if ( annotations.length === 0 ) {
return formats;
}

let record = { formats, text };
record = applyAnnotations( record, annotations );
return record.formats;
};
} );

/**
* Returns the annotations as a props object. Memoized to prevent re-renders.
*
* @param {Array} The annotations to put in the object.
*
* @return {Object} The annotations props object.
*/
const getAnnotationObject = memize( ( annotations ) => {
return {
annotations,
};
} );

export const annotation = {
name: FORMAT_NAME,
title: __( 'Annotation' ),
Expand All @@ -128,21 +167,9 @@ export const annotation = {
return null;
},
__experimentalGetPropsForEditableTreePreparation( select, { richTextIdentifier, blockClientId } ) {
return {
annotations: select( STORE_KEY ).__experimentalGetAnnotationsForRichText( blockClientId, richTextIdentifier ),
};
},
__experimentalCreatePrepareEditableTree( { annotations } ) {
return ( formats, text ) => {
if ( annotations.length === 0 ) {
return formats;
}

let record = { formats, text };
record = applyAnnotations( record, annotations );
return record.formats;
};
return getAnnotationObject( select( STORE_KEY ).__experimentalGetAnnotationsForRichText( blockClientId, richTextIdentifier ) );
},
__experimentalCreatePrepareEditableTree: createPrepareEditableTree,
__experimentalGetPropsForEditableTreeChangeHandler( dispatch ) {
return {
removeAnnotation: dispatch( STORE_KEY ).__experimentalRemoveAnnotation,
Expand Down
6 changes: 4 additions & 2 deletions packages/annotations/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import createSelector from 'rememo';
import { get, flatMap } from 'lodash';

const emptyArray = [];

/**
* Returns the annotations for a specific client ID.
*
Expand All @@ -19,7 +21,7 @@ export const __experimentalGetAnnotationsForBlock = createSelector(
} );
},
( state, blockClientId ) => [
get( state, blockClientId, [] ),
get( state, blockClientId, emptyArray ),
]
);

Expand Down Expand Up @@ -54,7 +56,7 @@ export const __experimentalGetAnnotationsForRichText = createSelector(
} );
},
( state, blockClientId ) => [
get( state, blockClientId, [] ),
get( state, blockClientId, emptyArray ),
]
);

Expand Down
25 changes: 17 additions & 8 deletions packages/rich-text/src/register-format-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
import { mapKeys } from 'lodash';
import memize from 'memize';

/**
* WordPress dependencies
Expand Down Expand Up @@ -119,6 +120,14 @@ export function registerFormatType( name, settings ) {

dispatch( 'core/rich-text' ).addFormatTypes( settings );

const emptyArray = [];
const getFunctionStackMemoized = memize( ( previousStack = emptyArray, newFunction ) => {
return [
...previousStack,
newFunction,
];
} );

if (
settings.__experimentalGetPropsForEditableTreePreparation
) {
Expand All @@ -133,13 +142,13 @@ export function registerFormatType( name, settings ) {
const additionalProps = {};

if ( settings.__experimentalCreatePrepareEditableTree ) {
additionalProps.prepareEditableTree = [
...( props.prepareEditableTree || [] ),
additionalProps.prepareEditableTree = getFunctionStackMemoized(
props.prepareEditableTree,
settings.__experimentalCreatePrepareEditableTree( props[ `format_${ name }` ], {
richTextIdentifier: props.identifier,
blockClientId: props.clientId,
} ),
];
} )
);
}

if ( settings.__experimentalCreateOnChangeEditableValue ) {
Expand All @@ -155,16 +164,16 @@ export function registerFormatType( name, settings ) {
return accumulator;
}, {} );

additionalProps.onChangeEditableValue = [
...( props.onChangeEditableValue || [] ),
additionalProps.onChangeEditableValue = getFunctionStackMemoized(
props.onChangeEditableValue,
settings.__experimentalCreateOnChangeEditableValue( {
...props[ `format_${ name }` ],
...dispatchProps,
}, {
richTextIdentifier: props.identifier,
blockClientId: props.clientId,
} ),
];
} )
);
}

return <OriginalComponent
Expand Down

0 comments on commit 254cf33

Please sign in to comment.