From 21937e224bcf0c9ec33aa46a94540f4d9d84b4df Mon Sep 17 00:00:00 2001 From: Ella Date: Wed, 3 Apr 2024 16:01:37 +0300 Subject: [PATCH 1/9] Block preview: build in async rendering --- packages/block-editor/package.json | 1 + .../src/components/block-preview/index.js | 28 +++++++++++++++++-- .../src/components/page-patterns/index.js | 1 - .../page-templates-template-parts/index.js | 4 --- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index dd4a58f1c91e3..56e4786090533 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -57,6 +57,7 @@ "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/preferences": "file:../preferences", + "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/private-apis": "file:../private-apis", "@wordpress/rich-text": "file:../rich-text", "@wordpress/style-engine": "file:../style-engine", diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 5968fa6f7aa7d..534b4f691b5bb 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -8,8 +8,9 @@ import classnames from 'classnames'; */ import { useDisabled, useMergeRefs } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; -import { memo, useMemo } from '@wordpress/element'; +import { memo, useMemo, useState, useEffect } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; +import { createQueue } from '@wordpress/priority-queue'; /** * Internal dependencies @@ -22,7 +23,7 @@ import { BlockListItems } from '../block-list'; const EMPTY_ADDITIONAL_STYLES = []; -export function BlockPreview( { +function AsyncBlockPreview( { blocks, viewportWidth = 1200, minHeight, @@ -86,6 +87,29 @@ export function BlockPreview( { ); } +const blockPreviewQueue = createQueue(); + +export function BlockPreview( props ) { + // const instanceId = useInstanceId( BlockPreview ); + const [ shouldRender, setShouldRender ] = useState( false ); + + useEffect( () => { + const context = {}; + blockPreviewQueue.add( context, () => { + setShouldRender( true ); + } ); + return () => { + blockPreviewQueue.remove( context ); + }; + }, [] ); + + if ( ! shouldRender ) { + return null; + } + + return ; +} + /** * BlockPreview renders a preview of a block or array of blocks. * diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 8ea0abb69bfcd..435568ade1d4d 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -404,7 +404,6 @@ export default function DataviewsPatterns() { isLoading={ isResolving } view={ view } onChangeView={ onChangeView } - deferredRendering supportedLayouts={ [ LAYOUT_GRID, LAYOUT_TABLE ] } /> diff --git a/packages/edit-site/src/components/page-templates-template-parts/index.js b/packages/edit-site/src/components/page-templates-template-parts/index.js index ebab114ec958e..9c86eddc1e456 100644 --- a/packages/edit-site/src/components/page-templates-template-parts/index.js +++ b/packages/edit-site/src/components/page-templates-template-parts/index.js @@ -419,10 +419,6 @@ export default function PageTemplatesTemplateParts( { postType } ) { view={ view } onChangeView={ onChangeView } onSelectionChange={ onSelectionChange } - deferredRendering={ - view.type === LAYOUT_GRID || - ! view.hiddenFields?.includes( 'preview' ) - } /> ); From c7711186999f08bc8ad674a2625b8551450aab47 Mon Sep 17 00:00:00 2001 From: Ella Date: Wed, 3 Apr 2024 16:06:11 +0300 Subject: [PATCH 2/9] Fix typo --- packages/block-editor/src/components/block-preview/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 534b4f691b5bb..6f01e4080aadc 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -99,7 +99,7 @@ export function BlockPreview( props ) { setShouldRender( true ); } ); return () => { - blockPreviewQueue.remove( context ); + blockPreviewQueue.cancel( context ); }; }, [] ); From eb45d344136c59ca233d6be7a45faa4306fa0cc0 Mon Sep 17 00:00:00 2001 From: Ella Date: Wed, 3 Apr 2024 16:07:45 +0300 Subject: [PATCH 3/9] Remove remnant comment --- packages/block-editor/src/components/block-preview/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 6f01e4080aadc..6f84d24a24140 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -90,7 +90,6 @@ function AsyncBlockPreview( { const blockPreviewQueue = createQueue(); export function BlockPreview( props ) { - // const instanceId = useInstanceId( BlockPreview ); const [ shouldRender, setShouldRender ] = useState( false ); useEffect( () => { From a43cebffea1bff55985430931b5725efb68434d0 Mon Sep 17 00:00:00 2001 From: Ella Date: Wed, 3 Apr 2024 17:05:56 +0300 Subject: [PATCH 4/9] Seprate Async util component --- packages/block-editor/package.json | 1 - .../src/components/block-preview/index.js | 27 +------------ packages/dataviews/README.md | 4 -- packages/dataviews/src/dataviews.js | 2 - packages/dataviews/src/view-grid.js | 8 +--- packages/dataviews/src/view-list.js | 11 ++---- packages/dataviews/src/view-table.js | 8 +--- packages/edit-site/package.json | 1 + .../edit-site/src/components/async/index.js | 39 +++++++++++++++++++ .../src/components/page-patterns/index.js | 11 ++++-- .../page-templates-template-parts/index.js | 5 ++- 11 files changed, 61 insertions(+), 56 deletions(-) create mode 100644 packages/edit-site/src/components/async/index.js diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 56e4786090533..dd4a58f1c91e3 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -57,7 +57,6 @@ "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/preferences": "file:../preferences", - "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/private-apis": "file:../private-apis", "@wordpress/rich-text": "file:../rich-text", "@wordpress/style-engine": "file:../style-engine", diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 6f84d24a24140..5968fa6f7aa7d 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -8,9 +8,8 @@ import classnames from 'classnames'; */ import { useDisabled, useMergeRefs } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; -import { memo, useMemo, useState, useEffect } from '@wordpress/element'; +import { memo, useMemo } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; -import { createQueue } from '@wordpress/priority-queue'; /** * Internal dependencies @@ -23,7 +22,7 @@ import { BlockListItems } from '../block-list'; const EMPTY_ADDITIONAL_STYLES = []; -function AsyncBlockPreview( { +export function BlockPreview( { blocks, viewportWidth = 1200, minHeight, @@ -87,28 +86,6 @@ function AsyncBlockPreview( { ); } -const blockPreviewQueue = createQueue(); - -export function BlockPreview( props ) { - const [ shouldRender, setShouldRender ] = useState( false ); - - useEffect( () => { - const context = {}; - blockPreviewQueue.add( context, () => { - setShouldRender( true ); - } ); - return () => { - blockPreviewQueue.cancel( context ); - }; - }, [] ); - - if ( ! shouldRender ) { - return null; - } - - return ; -} - /** * BlockPreview renders a preview of a block or array of blocks. * diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 59d5b5306a60d..d0eab0c46d059 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -275,10 +275,6 @@ Whether the data is loading. `false` by default. Array of layouts supported. By default, all are: `table`, `grid`, `list`. -### `deferredRendering`: `boolean` - -Whether the items should be rendered asynchronously. Useful when there's a field that takes a lot of time (e.g.: previews). `false` by default. - ### `onSelectionChange`: `function` Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. diff --git a/packages/dataviews/src/dataviews.js b/packages/dataviews/src/dataviews.js index 7e9a9482eec5a..d67115deb3d6b 100644 --- a/packages/dataviews/src/dataviews.js +++ b/packages/dataviews/src/dataviews.js @@ -41,7 +41,6 @@ export default function DataViews( { paginationInfo, supportedLayouts, onSelectionChange = defaultOnSelectionChange, - deferredRendering = false, } ) { const [ selection, setSelection ] = useState( [] ); const [ openedFilter, setOpenedFilter ] = useState( null ); @@ -136,7 +135,6 @@ export default function DataViews( { isLoading={ isLoading } onSelectionChange={ onSetSelection } selection={ selection } - deferredRendering={ deferredRendering } setOpenedFilter={ setOpenedFilter } /> { hasData && ( @@ -181,7 +177,7 @@ export default function ViewGrid( { className="dataviews-view-grid" aria-busy={ isLoading } > - { usedData.map( ( item ) => { + { data.map( ( item ) => { return ( + const selectedItem = data?.findLast( ( item ) => selection.includes( item.id ) ); @@ -166,7 +163,7 @@ export default function ViewList( { defaultActiveId: getItemDomId( selectedItem ), } ); - const hasData = usedData?.length; + const hasData = data?.length; if ( ! hasData ) { return (
- { usedData.map( ( item ) => { + { data.map( ( item ) => { const id = getItemDomId( item ); return ( { hasData && - usedData.map( ( item, index ) => ( + data.map( ( item, index ) => ( If there are multiple ongoing Transitions, React currently batches them + // > together. This is a limitation that will likely be removed in a future + // > release. + + useEffect( () => { + const context = {}; + blockPreviewQueue.add( context, () => { + setShouldRender( true ); + } ); + return () => { + blockPreviewQueue.cancel( context ); + }; + }, [] ); + + if ( ! shouldRender ) { + return null; + } + + return children; +} diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index 435568ade1d4d..f5a6d5f6bfc0a 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -34,6 +34,7 @@ import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies */ +import { Async } from '../async'; import Page from '../page'; import { LAYOUT_GRID, @@ -177,10 +178,12 @@ function Preview( { item, categoryId, viewType } ) { { isEmpty && isTemplatePart && __( 'Empty template part' ) } { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) } { ! isEmpty && ( - + + + ) }
diff --git a/packages/edit-site/src/components/page-templates-template-parts/index.js b/packages/edit-site/src/components/page-templates-template-parts/index.js index 9c86eddc1e456..17cf05e24158b 100644 --- a/packages/edit-site/src/components/page-templates-template-parts/index.js +++ b/packages/edit-site/src/components/page-templates-template-parts/index.js @@ -28,6 +28,7 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor'; /** * Internal dependencies */ +import { Async } from '../async'; import Page from '../page'; import { default as Link, useLink } from '../routes/link'; import AddNewTemplate from '../add-new-template'; @@ -173,7 +174,9 @@ function Preview( { item, viewType } ) { style={ { backgroundColor } } > { viewType === LAYOUT_LIST && ! isEmpty && ( - + + + ) } { viewType !== LAYOUT_LIST && ( ) } From 91d391958ae296c96a94bee4143d9123ebbfce27 Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 4 Apr 2024 12:52:37 +0300 Subject: [PATCH 6/9] Try react transition --- packages/edit-site/src/components/async/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/async/index.js b/packages/edit-site/src/components/async/index.js index ed1dc480c4d6e..632546f736c19 100644 --- a/packages/edit-site/src/components/async/index.js +++ b/packages/edit-site/src/components/async/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useEffect, useState } from '@wordpress/element'; +import { useEffect, useState, useTransition } from '@wordpress/element'; import { createQueue } from '@wordpress/priority-queue'; const blockPreviewQueue = createQueue(); @@ -12,6 +12,7 @@ const blockPreviewQueue = createQueue(); */ export function Async( { children, placeholder } ) { const [ shouldRender, setShouldRender ] = useState( false ); + const [ , startTransition ] = useTransition(); // In the future, we could try to use startTransition here, but currently // react will batch all transitions, which means all previews will be @@ -24,7 +25,9 @@ export function Async( { children, placeholder } ) { useEffect( () => { const context = {}; blockPreviewQueue.add( context, () => { - setShouldRender( true ); + startTransition( () => { + setShouldRender( true ); + } ); } ); return () => { blockPreviewQueue.cancel( context ); From ed71d1490c4b2ca47c7d87a495bb10194c091689 Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 4 Apr 2024 12:58:17 +0300 Subject: [PATCH 7/9] Remove spinners --- packages/edit-site/src/components/page-patterns/index.js | 3 +-- .../src/components/page-templates-template-parts/index.js | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js index c7933e03a912c..f5a6d5f6bfc0a 100644 --- a/packages/edit-site/src/components/page-patterns/index.js +++ b/packages/edit-site/src/components/page-patterns/index.js @@ -6,7 +6,6 @@ import { Button, Tooltip, Flex, - Spinner, } from '@wordpress/components'; import { getQueryArgs } from '@wordpress/url'; import { __, _x } from '@wordpress/i18n'; @@ -179,7 +178,7 @@ function Preview( { item, categoryId, viewType } ) { { isEmpty && isTemplatePart && __( 'Empty template part' ) } { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) } { ! isEmpty && ( - }> + { viewType === LAYOUT_LIST && ! isEmpty && ( - }> + ) } @@ -191,7 +190,7 @@ function Preview( { item, viewType } ) { ? __( 'Empty template' ) : __( 'Empty template part' ) ) } { ! isEmpty && ( - }> + ) } From 014409cff181cef5ed93af1f4b9f4fb5ac0ed29e Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 4 Apr 2024 14:02:29 +0300 Subject: [PATCH 8/9] Set state sync --- packages/edit-site/src/components/async/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/async/index.js b/packages/edit-site/src/components/async/index.js index 632546f736c19..ecbc9618f93ba 100644 --- a/packages/edit-site/src/components/async/index.js +++ b/packages/edit-site/src/components/async/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useEffect, useState, useTransition } from '@wordpress/element'; +import { useEffect, useState, flushSync } from '@wordpress/element'; import { createQueue } from '@wordpress/priority-queue'; const blockPreviewQueue = createQueue(); @@ -12,7 +12,6 @@ const blockPreviewQueue = createQueue(); */ export function Async( { children, placeholder } ) { const [ shouldRender, setShouldRender ] = useState( false ); - const [ , startTransition ] = useTransition(); // In the future, we could try to use startTransition here, but currently // react will batch all transitions, which means all previews will be @@ -25,7 +24,9 @@ export function Async( { children, placeholder } ) { useEffect( () => { const context = {}; blockPreviewQueue.add( context, () => { - startTransition( () => { + // Synchronously run all renders so it consumes timeRemaining. + // See https://github.com/WordPress/gutenberg/pull/48238 + flushSync( () => { setShouldRender( true ); } ); } ); From 0ec0b87eb918ce9c502d047b2b73dc10d62f7a2f Mon Sep 17 00:00:00 2001 From: Ella Date: Thu, 4 Apr 2024 14:17:26 +0300 Subject: [PATCH 9/9] Update package.json --- package-lock.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9066ae3524d61..51db8788ec604 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55728,6 +55728,7 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/preferences": "file:../preferences", "@wordpress/primitives": "file:../primitives", + "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/private-apis": "file:../private-apis", "@wordpress/reusable-blocks": "file:../reusable-blocks", "@wordpress/router": "file:../router", @@ -71490,6 +71491,7 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/preferences": "file:../preferences", "@wordpress/primitives": "file:../primitives", + "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/private-apis": "file:../private-apis", "@wordpress/reusable-blocks": "file:../reusable-blocks", "@wordpress/router": "file:../router",