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

Try reducing paragraph block rerendering #48460

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
44 changes: 38 additions & 6 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
useMemo,
useCallback,
RawHTML,
useRef,
} from '@wordpress/element';
import {
getBlockType,
Expand All @@ -28,8 +29,9 @@ import {
withSelect,
useDispatch,
useSelect,
useRegistry,
} from '@wordpress/data';
import { compose, pure, ifCondition } from '@wordpress/compose';
import { compose, pure } from '@wordpress/compose';
import { safeHTML } from '@wordpress/dom';

/**
Expand Down Expand Up @@ -78,7 +80,7 @@ function Block( { children, isHtml, ...props } ) {
}

function BlockListBlock( {
block: { __unstableBlockSource },
__unstableBlockSource,
mode,
isLocked,
canRemove,
Expand Down Expand Up @@ -283,7 +285,7 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId } ) => {
// This function should never be called when a block is not present in
// the state. It happens now because the order in withSelect rendering
// is not correct.
const { name, attributes, isValid } = block || {};
const { name, isValid, __unstableBlockSource } = block || {};

// Do not add new properties here, use `useSelect` instead to avoid
// leaking new props to the public API (editor.BlockListBlock filter).
Expand All @@ -297,10 +299,11 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId } ) => {
// access the block prop.
// Ideally these blocks would rely on the clientId prop only.
// This is kept for backward compatibility reasons.
block,
// block,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do: proxy block as well.

name,
attributes,
// attributes,
isValid,
__unstableBlockSource,
isSelected,
};
} );
Expand Down Expand Up @@ -540,9 +543,38 @@ export default compose(
pure,
applyWithSelect,
applyWithDispatch,
( WrappedComponent ) => ( props ) => {
const subscriptions = useRef( new Set() );
const registry = useRegistry();
const attributes = useSelect(
( select ) =>
Object.fromEntries(
Object.entries(
select( blockEditorStore ).getBlockAttributes(
props.clientId
)
).filter( ( [ key ] ) => subscriptions.current.has( key ) )
),
[ props.clientId ]
);

const proxy = new Proxy( attributes, {
get( target, name ) {
if ( target.hasOwnProperty( name ) ) {
return target[ name ];
}

subscriptions.current.add( name );
return registry
.select( blockEditorStore )
.getBlockAttributes( props.clientId )[ name ];
},
} );
return <WrappedComponent { ...props } attributes={ proxy } />;
ellatrix marked this conversation as resolved.
Show resolved Hide resolved
},
// Block is sometimes not mounted at the right time, causing it be undefined
// see issue for more info
// https://github.com/WordPress/gutenberg/issues/17013
ifCondition( ( { block } ) => !! block ),
// ifCondition( ( { block } ) => !! block ),
withFilters( 'editor.BlockListBlock' )
)( BlockListBlock );
4 changes: 2 additions & 2 deletions packages/block-editor/src/hooks/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export const withInspectorControls = createHigherOrderComponent(
*/
export const withLayoutStyles = createHigherOrderComponent(
( BlockListBlock ) => ( props ) => {
const { name, attributes, block } = props;
const { name, attributes } = props;
const hasLayoutBlockSupport = hasBlockSupport(
name,
layoutBlockSupportKey
Expand All @@ -372,7 +372,7 @@ export const withLayoutStyles = createHigherOrderComponent(
? { ...layout, type: 'constrained' }
: layout || defaultBlockLayout || {};
const layoutClasses = hasLayoutBlockSupport
? useLayoutClasses( block )
? useLayoutClasses( { name, attributes } )
: null;
// Higher specificity to override defaults from theme.json.
const selector = `.wp-container-${ id }.wp-container-${ id }`;
Expand Down
134 changes: 86 additions & 48 deletions packages/block-library/src/paragraph/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
RichText,
useBlockProps,
useSetting,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
import { formatLtr } from '@wordpress/icons';
Expand All @@ -27,6 +28,7 @@ import { formatLtr } from '@wordpress/icons';
* Internal dependencies
*/
import { useOnEnter } from './use-enter';
import { useSelect } from '@wordpress/data';

const name = 'core/paragraph';

Expand All @@ -49,6 +51,74 @@ function hasDropCapDisabled( align ) {
return align === ( isRTL() ? 'left' : 'right' ) || align === 'center';
}

// function useAttributes( name ) {
// return useSelect(
// ( select ) => select( blockEditorStore ).getAttribute( name ),
// [ name ]
// );
// }

function BlockContent( {
attributes,
mergeBlocks,
onReplace,
onRemove,
setAttributes,
clientId,
blockProps,
} ) {
const content = useSelect(
( select ) =>
select( blockEditorStore ).getBlockAttributes( clientId ).content,
[ clientId ]
);
const { placeholder } = attributes;
return (
<RichText
identifier="content"
tagName="p"
{ ...blockProps }
value={ content }
onChange={ ( newContent ) =>
setAttributes( { content: newContent } )
}
onSplit={ ( value, isOriginal ) => {
let newAttributes;

if ( isOriginal || value ) {
newAttributes = {
...attributes,
content: value,
};
}

const block = createBlock( name, newAttributes );

if ( isOriginal ) {
block.clientId = clientId;
}

return block;
} }
onMerge={ mergeBlocks }
onReplace={ onReplace }
onRemove={ onRemove }
aria-label={
content
? __( 'Paragraph block' )
: __(
'Empty block; start writing or type forward slash to choose a block'
)
}
data-empty={ content ? false : true }
placeholder={ placeholder || __( 'Type / to choose a block' ) }
data-custom-placeholder={ placeholder ? true : undefined }
__unstableEmbedURLOnPaste
__unstableAllowPrefixTransformations
/>
);
}

function ParagraphBlock( {
attributes,
mergeBlocks,
Expand All @@ -57,16 +127,8 @@ function ParagraphBlock( {
setAttributes,
clientId,
} ) {
const { align, content, direction, dropCap, placeholder } = attributes;
const { align, direction, dropCap } = attributes;
const isDropCapFeatureEnabled = useSetting( 'typography.dropCap' );
const blockProps = useBlockProps( {
ref: useOnEnter( { clientId, content } ),
className: classnames( {
'has-drop-cap': hasDropCapDisabled( align ) ? false : dropCap,
[ `has-text-align-${ align }` ]: align,
} ),
style: { direction },
} );

let helpText;
if ( hasDropCapDisabled( align ) ) {
Expand All @@ -77,6 +139,15 @@ function ParagraphBlock( {
helpText = __( 'Toggle to show a large initial letter.' );
}

const blockProps = useBlockProps( {
ref: useOnEnter( { clientId } ),
className: classnames( {
'has-drop-cap': hasDropCapDisabled( align ) ? false : dropCap,
[ `has-text-align-${ align }` ]: align,
} ),
style: { direction },
} );

return (
<>
<BlockControls group="block">
Expand Down Expand Up @@ -123,47 +194,14 @@ function ParagraphBlock( {
</ToolsPanelItem>
</InspectorControls>
) }
<RichText
identifier="content"
tagName="p"
{ ...blockProps }
value={ content }
onChange={ ( newContent ) =>
setAttributes( { content: newContent } )
}
onSplit={ ( value, isOriginal ) => {
let newAttributes;

if ( isOriginal || value ) {
newAttributes = {
...attributes,
content: value,
};
}

const block = createBlock( name, newAttributes );

if ( isOriginal ) {
block.clientId = clientId;
}

return block;
} }
onMerge={ mergeBlocks }
<BlockContent
attributes={ attributes }
mergeBlocks={ mergeBlocks }
onReplace={ onReplace }
onRemove={ onRemove }
aria-label={
content
? __( 'Paragraph block' )
: __(
'Empty block; start writing or type forward slash to choose a block'
)
}
data-empty={ content ? false : true }
placeholder={ placeholder || __( 'Type / to choose a block' ) }
data-custom-placeholder={ placeholder ? true : undefined }
__unstableEmbedURLOnPaste
__unstableAllowPrefixTransformations
setAttributes={ setAttributes }
clientId={ clientId }
blockProps={ blockProps }
/>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion packages/block-library/src/paragraph/use-enter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function useOnEnter( props ) {
getBlockName,
getBlock,
getNextBlockClientId,
getBlockAttributes,
} = useSelect( blockEditorStore );
const propsRef = useRef( props );
propsRef.current = props;
Expand All @@ -36,7 +37,8 @@ export function useOnEnter( props ) {
return;
}

const { content, clientId } = propsRef.current;
const { clientId } = propsRef.current;
const { content } = getBlockAttributes( clientId );

// The paragraph should be empty.
if ( content.length ) {
Expand Down