Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit e81ad0c

Browse files
committed
move from class to functional component
1 parent dca174b commit e81ad0c

File tree

3 files changed

+91
-123
lines changed

3 files changed

+91
-123
lines changed

assets/js/blocks/products/all-products/edit.tsx

Lines changed: 86 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,17 @@ import {
88
InnerBlocks,
99
InspectorControls,
1010
} from '@wordpress/block-editor';
11-
import { withDispatch, withSelect } from '@wordpress/data';
11+
import { useSelect, useDispatch } from '@wordpress/data';
1212
import {
1313
PanelBody,
14-
withSpokenMessages,
1514
Placeholder,
1615
Button,
1716
ToolbarGroup,
1817
Disabled,
1918
Tip,
2019
} from '@wordpress/components';
21-
import { Component } from '@wordpress/element';
22-
import { compose } from '@wordpress/compose';
20+
import { useState, useEffect } from '@wordpress/element';
21+
import { useDebounce } from '@wordpress/compose';
2322
import { Icon, grid } from '@wordpress/icons';
2423
import GridLayoutControl from '@woocommerce/editor-components/grid-layout-control';
2524
import {
@@ -30,6 +29,7 @@ import { getBlockMap } from '@woocommerce/atomic-utils';
3029
import { previewProducts } from '@woocommerce/resource-previews';
3130
import { getSetting } from '@woocommerce/settings';
3231
import { blocksConfig } from '@woocommerce/block-settings';
32+
import { speak } from '@wordpress/a11y';
3333

3434
/**
3535
* Internal dependencies
@@ -47,63 +47,58 @@ import { getSharedContentControls, getSharedListControls } from '../edit';
4747
import Block from './block';
4848
import './editor.scss';
4949

50-
type EditorAttributes = {
50+
type Attributes = {
5151
columns: number;
5252
rows: number;
5353
alignButtons: boolean;
54-
contentVisibility: object;
55-
orderby: string;
56-
layoutConfig: Array< object >;
57-
isPreview: boolean;
54+
layoutConfig: [ string, object? ][];
5855
};
5956

60-
interface EditorProps {
61-
block: BlockInstance;
62-
attributes: EditorAttributes;
63-
debouncedSpeak: ( label: string ) => void;
57+
type Props = {
58+
contentVisibility: number;
59+
orderby: number;
60+
isPreview: number;
61+
clientId: string;
62+
attributes: Attributes;
6463
setAttributes: ( attributes: Record< string, unknown > ) => void;
65-
replaceInnerBlocks: (
66-
rootClientId: string,
67-
blocks: BlockInstance[],
68-
updateSelection?: boolean
69-
) => void;
70-
}
64+
};
7165

72-
interface EditorState {
73-
isEditing: boolean;
74-
innerBlocks: BlockInstance[];
75-
}
66+
export const Edit = ( props: Props ): JSX.Element => {
67+
const [ isEditing, setIsEditing ] = useState< boolean >( false );
68+
const [ , setInnerBlocks ] = useState< BlockInstance[] | boolean >( false );
69+
const blockMap = getBlockMap( 'woocommerce/all-products' );
7670

77-
/**
78-
* Component to handle edit mode of "All Products".
79-
*/
80-
class Editor extends Component< EditorProps, EditorState > {
81-
state = {
82-
isEditing: false,
83-
innerBlocks: [],
84-
};
71+
const { clientId, attributes, setAttributes } = props;
8572

86-
blockMap = getBlockMap( 'woocommerce/all-products' );
73+
const { columns, rows, alignButtons, layoutConfig } = attributes;
8774

88-
componentDidMount = (): void => {
89-
const { block } = this.props;
90-
this.setState( { innerBlocks: block.innerBlocks } );
91-
};
75+
const { innerBlocks } = useSelect( ( select ) => {
76+
const { getBlock } = select( 'core/block-editor' );
77+
const block = getBlock( clientId );
78+
return {
79+
innerBlocks: block ? block.innerBlocks : [],
80+
};
81+
} );
82+
83+
useEffect( () => {
84+
setInnerBlocks( innerBlocks );
85+
}, [] );
86+
87+
const { replaceInnerBlocks } = useDispatch( 'core/block-editor' );
88+
const debouncedSpeak = useDebounce( speak );
9289

93-
getTitle = (): string => {
90+
const getTitle = (): string => {
9491
return __( 'All Products', 'woo-gutenberg-products-block' );
9592
};
9693

97-
getIcon = (): JSX.Element => {
94+
const getIcon = (): JSX.Element => {
9895
return <Icon icon={ grid } />;
9996
};
10097

101-
togglePreview = (): void => {
102-
const { debouncedSpeak } = this.props;
98+
const togglePreview = (): void => {
99+
setIsEditing( ! isEditing );
103100

104-
this.setState( { isEditing: ! this.state.isEditing } );
105-
106-
if ( ! this.state.isEditing ) {
101+
if ( ! isEditing ) {
107102
debouncedSpeak(
108103
__(
109104
'Showing All Products block preview.',
@@ -113,10 +108,7 @@ class Editor extends Component< EditorProps, EditorState > {
113108
}
114109
};
115110

116-
getInspectorControls = (): JSX.Element => {
117-
const { attributes, setAttributes } = this.props;
118-
const { columns, rows, alignButtons } = attributes;
119-
111+
const getInspectorControls = (): JSX.Element => {
120112
return (
121113
<InspectorControls key="inspector">
122114
<PanelBody
@@ -131,10 +123,10 @@ class Editor extends Component< EditorProps, EditorState > {
131123
rows={ rows }
132124
alignButtons={ alignButtons }
133125
setAttributes={ setAttributes }
134-
minColumns={ getSetting( 'min_columns', 1 ) }
135-
maxColumns={ getSetting( 'max_columns', 6 ) }
136-
minRows={ getSetting( 'min_rows', 1 ) }
137-
maxRows={ getSetting( 'max_rows', 6 ) }
126+
minColumns={ getSetting( 'min_columns', 1 ) as number }
127+
maxColumns={ getSetting( 'max_columns', 6 ) as number }
128+
minRows={ getSetting( 'min_rows', 1 ) as number }
129+
maxRows={ getSetting( 'max_rows', 6 ) as number }
138130
/>
139131
</PanelBody>
140132
<PanelBody
@@ -150,9 +142,7 @@ class Editor extends Component< EditorProps, EditorState > {
150142
);
151143
};
152144

153-
getBlockControls = (): JSX.Element => {
154-
const { isEditing } = this.state;
155-
145+
const getBlockControls = (): JSX.Element => {
156146
return (
157147
<BlockControls>
158148
<ToolbarGroup
@@ -163,7 +153,7 @@ class Editor extends Component< EditorProps, EditorState > {
163153
'Edit the layout of each product',
164154
'woo-gutenberg-products-block'
165155
),
166-
onClick: () => this.togglePreview(),
156+
onClick: () => togglePreview(),
167157
isActive: isEditing,
168158
},
169159
] }
@@ -172,47 +162,47 @@ class Editor extends Component< EditorProps, EditorState > {
172162
);
173163
};
174164

175-
renderEditMode = () => {
165+
const renderEditMode = () => {
176166
const onDone = () => {
177-
const { block, setAttributes } = this.props;
178167
setAttributes( {
179-
layoutConfig: getProductLayoutConfig( block.innerBlocks ),
168+
layoutConfig: getProductLayoutConfig( innerBlocks ),
180169
} );
181-
this.setState( { innerBlocks: block.innerBlocks } );
182-
this.togglePreview();
170+
setInnerBlocks( innerBlocks );
171+
togglePreview();
183172
};
184173

185174
const onCancel = () => {
186-
const { block, replaceInnerBlocks } = this.props;
187-
const { innerBlocks } = this.state;
188-
replaceInnerBlocks( block.clientId, innerBlocks, false );
189-
this.togglePreview();
175+
replaceInnerBlocks( clientId, innerBlocks, false );
176+
togglePreview();
190177
};
191178

192179
const onReset = () => {
193-
const { block, replaceInnerBlocks } = this.props;
194180
const newBlocks: BlockInstance[] = [];
195-
DEFAULT_PRODUCT_LIST_LAYOUT.map( ( [ name, attributes ] ) => {
196-
newBlocks.push( createBlock( name, attributes ) );
181+
DEFAULT_PRODUCT_LIST_LAYOUT.map( ( [ name, blockAttributes ] ) => {
182+
newBlocks.push( createBlock( name, blockAttributes ) );
197183
return true;
198184
} );
199-
replaceInnerBlocks( block.clientId, newBlocks, false );
200-
this.setState( { innerBlocks: block.innerBlocks } );
185+
replaceInnerBlocks( clientId, newBlocks, false );
186+
setInnerBlocks( innerBlocks );
201187
};
202188

203-
const InnerBlockProps = {
204-
template: this.props.attributes.layoutConfig,
189+
const InnerBlockProps: {
190+
template: [ string, object? ][];
191+
templateLock: boolean;
192+
allowedBlocks: Array< string >;
193+
renderAppender?: undefined | boolean;
194+
} = {
195+
template: layoutConfig,
205196
templateLock: false,
206-
allowedBlocks: Object.keys( this.blockMap ),
207-
renderAppender: true,
197+
allowedBlocks: Object.keys( blockMap ),
208198
};
209199

210-
if ( this.props.attributes.layoutConfig.length !== 0 ) {
200+
if ( layoutConfig.length !== 0 ) {
211201
InnerBlockProps.renderAppender = false;
212202
}
213203

214204
return (
215-
<Placeholder icon={ this.getIcon() } label={ this.getTitle() }>
205+
<Placeholder icon={ getIcon() } label={ getTitle() }>
216206
{ __(
217207
'Display all products from your store as a grid.',
218208
'woo-gutenberg-products-block'
@@ -277,12 +267,10 @@ class Editor extends Component< EditorProps, EditorState > {
277267
);
278268
};
279269

280-
renderViewMode = () => {
281-
const { attributes } = this.props;
282-
const { layoutConfig } = attributes;
270+
const renderViewMode = () => {
283271
const hasContent = layoutConfig && layoutConfig.length !== 0;
284-
const blockTitle = this.getTitle();
285-
const blockIcon = this.getIcon();
272+
const blockTitle = getTitle();
273+
const blockIcon = getIcon();
286274

287275
if ( ! hasContent ) {
288276
return renderHiddenContentPlaceholder( blockTitle, blockIcon );
@@ -296,43 +284,23 @@ class Editor extends Component< EditorProps, EditorState > {
296284
);
297285
};
298286

299-
render = () => {
300-
const { attributes } = this.props;
301-
const { isEditing } = this.state;
302-
const blockTitle = this.getTitle();
303-
const blockIcon = this.getIcon();
287+
const blockTitle = getTitle();
288+
const blockIcon = getIcon();
304289

305-
if ( blocksConfig.productCount === 0 ) {
306-
return renderNoProductsPlaceholder( blockTitle, blockIcon );
307-
}
308-
309-
return (
310-
<div
311-
className={ getBlockClassName(
312-
'wc-block-all-products',
313-
attributes
314-
) }
315-
>
316-
{ this.getBlockControls() }
317-
{ this.getInspectorControls() }
318-
{ isEditing ? this.renderEditMode() : this.renderViewMode() }
319-
</div>
320-
);
321-
};
322-
}
290+
if ( blocksConfig.productCount === 0 ) {
291+
return renderNoProductsPlaceholder( blockTitle, blockIcon );
292+
}
323293

324-
export default compose(
325-
withSpokenMessages,
326-
withSelect( ( select, { clientId } ) => {
327-
const { getBlock } = select( 'core/block-editor' );
328-
return {
329-
block: getBlock( clientId ),
330-
};
331-
} ),
332-
withDispatch( ( dispatch ) => {
333-
const { replaceInnerBlocks } = dispatch( 'core/block-editor' );
334-
return {
335-
replaceInnerBlocks,
336-
};
337-
} )
338-
)( Editor );
294+
return (
295+
<div
296+
className={ getBlockClassName(
297+
'wc-block-all-products',
298+
attributes
299+
) }
300+
>
301+
{ getBlockControls() }
302+
{ getInspectorControls() }
303+
{ isEditing ? renderEditMode() : renderViewMode() }
304+
</div>
305+
);
306+
};

assets/js/blocks/products/all-products/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import '@woocommerce/atomic-blocks';
1010
*/
1111
import metadata from './block.json';
1212
import deprecated from './deprecated';
13-
import edit from './edit';
14-
import save from './save';
13+
import { Edit } from './edit';
14+
import Save from './save';
1515
import defaults from './defaults';
1616

1717
const { name } = metadata;
@@ -26,9 +26,9 @@ const settings = {
2626
/>
2727
),
2828
},
29-
edit,
29+
edit: Edit,
3030
// Save the props to post content.
31-
save,
31+
save: Save,
3232
deprecated,
3333
defaults,
3434
};

assets/js/blocks/products/all-products/save.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { InnerBlocks } from '@wordpress/block-editor';
88
*/
99
import { getBlockClassName } from '../utils.js';
1010

11-
export default function save( { attributes } ) {
11+
export default function Save( { attributes } ) {
1212
const dataAttributes = {};
1313
Object.keys( attributes )
1414
.sort()

0 commit comments

Comments
 (0)