From 3265f613139ae6c5520af79e6fd023f1043a8c7d Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 18 Dec 2023 20:51:10 +0400 Subject: [PATCH 1/8] Block Supports: Try using 'memo' instead of 'pure' --- packages/block-editor/src/hooks/utils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index cd660c85826c28..e63029e4e34e81 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -2,9 +2,9 @@ * WordPress dependencies */ import { getBlockSupport } from '@wordpress/blocks'; -import { useMemo, useEffect, useId, useState } from '@wordpress/element'; +import { memo, useMemo, useEffect, useId, useState } from '@wordpress/element'; import { useDispatch } from '@wordpress/data'; -import { createHigherOrderComponent, pure } from '@wordpress/compose'; +import { createHigherOrderComponent } from '@wordpress/compose'; import { addFilter } from '@wordpress/hooks'; /** @@ -402,10 +402,10 @@ export function useBlockSettings( name, parentLayout ) { export function createBlockEditFilter( features ) { // We don't want block controls to re-render when typing inside a block. - // `pure` will prevent re-renders unless props change, so only pass the + // `memo` will prevent re-renders unless props change, so only pass the // needed props and not the whole attributes object. features = features.map( ( settings ) => { - return { ...settings, Edit: pure( settings.edit ) }; + return { ...settings, Edit: memo( settings.edit ) }; } ); const withBlockEditHooks = createHigherOrderComponent( ( OriginalBlockEdit ) => ( props ) => { @@ -488,7 +488,7 @@ function BlockProps( { index, useBlockProps, setAllWrapperProps, ...props } ) { return null; } -const BlockPropsPure = pure( BlockProps ); +const BlockPropsPure = memo( BlockProps ); export function createBlockListBlockFilter( features ) { const withBlockListBlockHooks = createHigherOrderComponent( From 67e3a46d13f2e6c92470e9b428f9f3c777c606e1 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 19 Dec 2023 10:35:26 +0400 Subject: [PATCH 2/8] Replace more occurrences --- packages/block-editor/src/components/block-list/block.js | 6 +++--- packages/block-editor/src/components/block-preview/auto.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index af96f0e3483d1c..7690386764f6cc 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { useCallback, RawHTML, useContext } from '@wordpress/element'; +import { memo, useCallback, RawHTML, useContext } from '@wordpress/element'; import { getBlockType, getSaveContent, @@ -21,7 +21,7 @@ import { } from '@wordpress/blocks'; import { withFilters } from '@wordpress/components'; import { withDispatch, useDispatch, useSelect } from '@wordpress/data'; -import { compose, pure } from '@wordpress/compose'; +import { compose } from '@wordpress/compose'; import { safeHTML } from '@wordpress/dom'; /** @@ -739,4 +739,4 @@ function BlockListBlockProvider( props ) { ); } -export default pure( BlockListBlockProvider ); +export default memo( BlockListBlockProvider ); diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index 8972370cac6897..b4fa5e27b072ef 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -1,9 +1,9 @@ /** * WordPress dependencies */ -import { useResizeObserver, pure, useRefEffect } from '@wordpress/compose'; +import { useResizeObserver, useRefEffect } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; -import { useMemo } from '@wordpress/element'; +import { memo, useMemo } from '@wordpress/element'; import { Disabled } from '@wordpress/components'; /** @@ -55,7 +55,7 @@ function ScaledBlockPreview( { }, [ styles, additionalStyles ] ); // Initialize on render instead of module top level, to avoid circular dependency issues. - MemoizedBlockList = MemoizedBlockList || pure( BlockList ); + MemoizedBlockList = MemoizedBlockList || memo( BlockList ); const scale = containerWidth / viewportWidth; const aspectRatio = contentHeight From 7369cfa45e2598c781e55f614f713d839685472e Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 19 Dec 2023 17:19:18 +0400 Subject: [PATCH 3/8] Deprecate 'pure' HoC --- packages/compose/README.md | 2 ++ packages/compose/src/higher-order/pure/index.tsx | 8 ++++++++ packages/compose/src/higher-order/pure/test/index.js | 9 +++++++++ packages/data/src/components/with-select/index.js | 5 +++-- packages/viewport/src/with-viewport-match.js | 4 ++-- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/compose/README.md b/packages/compose/README.md index ce393f2b5fd18c..7eb70a7300f07f 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -141,6 +141,8 @@ _Related_ ### pure +> **Deprecated** Use `memo` or `PureComponent` instead. + Given a component returns the enhanced component augmented with a component only re-rendering when its props/state change ### throttle diff --git a/packages/compose/src/higher-order/pure/index.tsx b/packages/compose/src/higher-order/pure/index.tsx index 65684738b708ac..ce9dbba96195e0 100644 --- a/packages/compose/src/higher-order/pure/index.tsx +++ b/packages/compose/src/higher-order/pure/index.tsx @@ -8,6 +8,7 @@ import type { ComponentType, ComponentClass } from 'react'; */ import isShallowEqual from '@wordpress/is-shallow-equal'; import { Component } from '@wordpress/element'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -17,10 +18,17 @@ import { createHigherOrderComponent } from '../../utils/create-higher-order-comp /** * Given a component returns the enhanced component augmented with a component * only re-rendering when its props/state change + * + * @deprecated Use `memo` or `PureComponent` instead. */ const pure = createHigherOrderComponent( function < Props extends {} >( WrappedComponent: ComponentType< Props > ): ComponentType< Props > { + deprecated( 'wp.compose.pure', { + since: '6.5', + alternative: 'Use `memo` or `PureComponent` instead', + } ); + if ( WrappedComponent.prototype instanceof Component ) { return class extends ( WrappedComponent as ComponentClass< Props > ) { shouldComponentUpdate( nextProps: Props, nextState: any ) { diff --git a/packages/compose/src/higher-order/pure/test/index.js b/packages/compose/src/higher-order/pure/test/index.js index 4285d9228c45d3..0e5b80d0124356 100644 --- a/packages/compose/src/higher-order/pure/test/index.js +++ b/packages/compose/src/higher-order/pure/test/index.js @@ -8,6 +8,7 @@ import userEvent from '@testing-library/user-event'; * WordPress dependencies */ import { Component } from '@wordpress/element'; +import { logged } from '@wordpress/deprecated'; /** * Internal dependencies @@ -15,6 +16,12 @@ import { Component } from '@wordpress/element'; import pure from '../'; describe( 'pure', () => { + afterEach( () => { + for ( const key in logged ) { + delete logged[ key ]; + } + } ); + it( 'functional component should rerender only when props change', () => { let i = 0; const MyComp = pure( () => { @@ -24,6 +31,7 @@ describe( 'pure', () => { // Updating with same props doesn't rerender. rerender( ); + expect( console ).toHaveWarned(); expect( screen.getByTestId( 'counter' ) ).toHaveTextContent( '1' ); // New prop should trigger a rerender. @@ -74,6 +82,7 @@ describe( 'pure', () => { ); const { rerender } = render( ); + expect( console ).toHaveWarned(); // Updating with same props doesn't rerender. rerender( ); diff --git a/packages/data/src/components/with-select/index.js b/packages/data/src/components/with-select/index.js index 12a56b70da2b65..967970ce938738 100644 --- a/packages/data/src/components/with-select/index.js +++ b/packages/data/src/components/with-select/index.js @@ -1,7 +1,8 @@ /** * WordPress dependencies */ -import { createHigherOrderComponent, pure } from '@wordpress/compose'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { memo } from '@wordpress/element'; /** * Internal dependencies @@ -53,7 +54,7 @@ import useSelect from '../use-select'; const withSelect = ( mapSelectToProps ) => createHigherOrderComponent( ( WrappedComponent ) => - pure( ( ownProps ) => { + memo( ( ownProps ) => { const mapSelect = ( select, registry ) => mapSelectToProps( select, ownProps, registry ); const mergeProps = useSelect( mapSelect ); diff --git a/packages/viewport/src/with-viewport-match.js b/packages/viewport/src/with-viewport-match.js index ebcbd96726e114..b031fac347f37d 100644 --- a/packages/viewport/src/with-viewport-match.js +++ b/packages/viewport/src/with-viewport-match.js @@ -3,9 +3,9 @@ */ import { createHigherOrderComponent, - pure, useViewportMatch, } from '@wordpress/compose'; +import { memo } from '@wordpress/element'; /** * Higher-order component creator, creating a new component which renders with @@ -48,7 +48,7 @@ const withViewportMatch = ( queries ) => { } ) ); return createHigherOrderComponent( ( WrappedComponent ) => { - return pure( ( props ) => { + return memo( ( props ) => { const queriesResult = useViewPortQueriesResult(); return ; } ); From 2304b827606510979b4b4754aa767215660a4b6d Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 19 Dec 2023 17:32:06 +0400 Subject: [PATCH 4/8] Update native file --- packages/block-editor/src/hooks/typography.native.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/typography.native.js b/packages/block-editor/src/hooks/typography.native.js index d8cbf71d84e13f..f0e9c9c10913d7 100644 --- a/packages/block-editor/src/hooks/typography.native.js +++ b/packages/block-editor/src/hooks/typography.native.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { pure } from '@wordpress/compose'; +import { memo } from '@wordpress/element'; import { PanelBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -57,4 +57,4 @@ function TypographyPanelPure( { clientId, setAttributes, settings } ) { // We don't want block controls to re-render when typing inside a block. `pure` // will prevent re-renders unless props change, so only pass the needed props // and not the whole attributes object. -export const TypographyPanel = pure( TypographyPanelPure ); +export const TypographyPanel = memo( TypographyPanelPure ); From bbb678ca639b397d641c2ac51d88fbc0138c19d0 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 19 Dec 2023 17:44:19 +0400 Subject: [PATCH 5/8] Blame failed search --- .../src/components/block-list/block.native.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.native.js b/packages/block-editor/src/components/block-list/block.native.js index c4f86cfe25a428..1c0de681bd4c29 100644 --- a/packages/block-editor/src/components/block-list/block.native.js +++ b/packages/block-editor/src/components/block-list/block.native.js @@ -7,7 +7,13 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { useCallback, useMemo, useState, useRef } from '@wordpress/element'; +import { + useCallback, + useMemo, + useState, + useRef, + memo, +} from '@wordpress/element'; import { GlobalStylesContext, getMergedGlobalStyles, @@ -29,7 +35,7 @@ import { withDispatch, withSelect, } from '@wordpress/data'; -import { compose, ifCondition, pure } from '@wordpress/compose'; +import { compose, ifCondition } from '@wordpress/compose'; /** * Internal dependencies @@ -682,7 +688,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { } ); export default compose( - pure, + memo, applyWithSelect, applyWithDispatch, // Block is sometimes not mounted at the right time, causing it be undefined From ad3c8a2ff0edfad3d28bf75121dfa9a79c9b24ad Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 22 Dec 2023 16:35:19 +0400 Subject: [PATCH 6/8] Use toHaveWarnedWith --- packages/compose/src/higher-order/pure/test/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/compose/src/higher-order/pure/test/index.js b/packages/compose/src/higher-order/pure/test/index.js index 0e5b80d0124356..3444624fe17145 100644 --- a/packages/compose/src/higher-order/pure/test/index.js +++ b/packages/compose/src/higher-order/pure/test/index.js @@ -31,7 +31,9 @@ describe( 'pure', () => { // Updating with same props doesn't rerender. rerender( ); - expect( console ).toHaveWarned(); + expect( console ).toHaveWarnedWith( + 'wp.compose.pure is deprecated since version 6.5. Please use Use `memo` or `PureComponent` instead instead.' + ); expect( screen.getByTestId( 'counter' ) ).toHaveTextContent( '1' ); // New prop should trigger a rerender. @@ -82,7 +84,9 @@ describe( 'pure', () => { ); const { rerender } = render( ); - expect( console ).toHaveWarned(); + expect( console ).toHaveWarnedWith( + 'wp.compose.pure is deprecated since version 6.5. Please use Use `memo` or `PureComponent` instead instead.' + ); // Updating with same props doesn't rerender. rerender( ); From 044154f211677d5863f12f0877954ee4c12f80d7 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 19 Jan 2024 14:59:41 +0400 Subject: [PATCH 7/8] Soft deprecate --- packages/compose/src/higher-order/pure/index.tsx | 6 ------ .../compose/src/higher-order/pure/test/index.js | 14 -------------- packages/data/src/components/with-select/index.js | 5 ++--- packages/viewport/src/with-viewport-match.js | 4 ++-- 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/packages/compose/src/higher-order/pure/index.tsx b/packages/compose/src/higher-order/pure/index.tsx index ce9dbba96195e0..38a85a5eebe9ab 100644 --- a/packages/compose/src/higher-order/pure/index.tsx +++ b/packages/compose/src/higher-order/pure/index.tsx @@ -8,7 +8,6 @@ import type { ComponentType, ComponentClass } from 'react'; */ import isShallowEqual from '@wordpress/is-shallow-equal'; import { Component } from '@wordpress/element'; -import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -24,11 +23,6 @@ import { createHigherOrderComponent } from '../../utils/create-higher-order-comp const pure = createHigherOrderComponent( function < Props extends {} >( WrappedComponent: ComponentType< Props > ): ComponentType< Props > { - deprecated( 'wp.compose.pure', { - since: '6.5', - alternative: 'Use `memo` or `PureComponent` instead', - } ); - if ( WrappedComponent.prototype instanceof Component ) { return class extends ( WrappedComponent as ComponentClass< Props > ) { shouldComponentUpdate( nextProps: Props, nextState: any ) { diff --git a/packages/compose/src/higher-order/pure/test/index.js b/packages/compose/src/higher-order/pure/test/index.js index 3444624fe17145..7efc5fd1beb76f 100644 --- a/packages/compose/src/higher-order/pure/test/index.js +++ b/packages/compose/src/higher-order/pure/test/index.js @@ -8,20 +8,12 @@ import userEvent from '@testing-library/user-event'; * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { logged } from '@wordpress/deprecated'; - /** * Internal dependencies */ import pure from '../'; describe( 'pure', () => { - afterEach( () => { - for ( const key in logged ) { - delete logged[ key ]; - } - } ); - it( 'functional component should rerender only when props change', () => { let i = 0; const MyComp = pure( () => { @@ -31,9 +23,6 @@ describe( 'pure', () => { // Updating with same props doesn't rerender. rerender( ); - expect( console ).toHaveWarnedWith( - 'wp.compose.pure is deprecated since version 6.5. Please use Use `memo` or `PureComponent` instead instead.' - ); expect( screen.getByTestId( 'counter' ) ).toHaveTextContent( '1' ); // New prop should trigger a rerender. @@ -84,9 +73,6 @@ describe( 'pure', () => { ); const { rerender } = render( ); - expect( console ).toHaveWarnedWith( - 'wp.compose.pure is deprecated since version 6.5. Please use Use `memo` or `PureComponent` instead instead.' - ); // Updating with same props doesn't rerender. rerender( ); diff --git a/packages/data/src/components/with-select/index.js b/packages/data/src/components/with-select/index.js index 967970ce938738..12a56b70da2b65 100644 --- a/packages/data/src/components/with-select/index.js +++ b/packages/data/src/components/with-select/index.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { createHigherOrderComponent } from '@wordpress/compose'; -import { memo } from '@wordpress/element'; +import { createHigherOrderComponent, pure } from '@wordpress/compose'; /** * Internal dependencies @@ -54,7 +53,7 @@ import useSelect from '../use-select'; const withSelect = ( mapSelectToProps ) => createHigherOrderComponent( ( WrappedComponent ) => - memo( ( ownProps ) => { + pure( ( ownProps ) => { const mapSelect = ( select, registry ) => mapSelectToProps( select, ownProps, registry ); const mergeProps = useSelect( mapSelect ); diff --git a/packages/viewport/src/with-viewport-match.js b/packages/viewport/src/with-viewport-match.js index b031fac347f37d..ebcbd96726e114 100644 --- a/packages/viewport/src/with-viewport-match.js +++ b/packages/viewport/src/with-viewport-match.js @@ -3,9 +3,9 @@ */ import { createHigherOrderComponent, + pure, useViewportMatch, } from '@wordpress/compose'; -import { memo } from '@wordpress/element'; /** * Higher-order component creator, creating a new component which renders with @@ -48,7 +48,7 @@ const withViewportMatch = ( queries ) => { } ) ); return createHigherOrderComponent( ( WrappedComponent ) => { - return memo( ( props ) => { + return pure( ( props ) => { const queriesResult = useViewPortQueriesResult(); return ; } ); From fc8f53a804630dde89248830dce3581f7c94bb93 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 19 Jan 2024 17:22:02 +0400 Subject: [PATCH 8/8] Add changelong entry --- packages/compose/CHANGELOG.md | 4 ++++ packages/compose/src/higher-order/pure/test/index.js | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 25ea99778733f6..54ff6a16252e37 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- The `pure` HoC has been deprecated. Use `memo` or `PureComponent` instead ([#57173](https://github.com/WordPress/gutenberg/pull/57173)). + ## 6.26.0 (2024-01-10) ## 6.25.0 (2023-12-13) diff --git a/packages/compose/src/higher-order/pure/test/index.js b/packages/compose/src/higher-order/pure/test/index.js index 7efc5fd1beb76f..4285d9228c45d3 100644 --- a/packages/compose/src/higher-order/pure/test/index.js +++ b/packages/compose/src/higher-order/pure/test/index.js @@ -8,6 +8,7 @@ import userEvent from '@testing-library/user-event'; * WordPress dependencies */ import { Component } from '@wordpress/element'; + /** * Internal dependencies */