Skip to content

Commit

Permalink
Extract Navigation Block data fetching and management to hook(s) (#31825
Browse files Browse the repository at this point in the history
)

* Moving managing data for Navigation entities into hook

* Refactor to individual hooks for pages and menus entities

* Refactor menuItem to seperate entity

* Perf optimise with empty dep array on useSelect

* Move has* into the select

* Tidy up menu items from menus hook

* Fix error caused by moving has* within the useSelect
  • Loading branch information
getdave authored May 14, 2021
1 parent f21f09d commit 80a2a1c
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 67 deletions.
72 changes: 5 additions & 67 deletions packages/block-library/src/navigation/placeholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
MenuItem,
Spinner,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';

import {
forwardRef,
useCallback,
Expand All @@ -19,12 +19,11 @@ import {
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { navigation, chevronDown, Icon } from '@wordpress/icons';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/

import useNavigationEntities from './use-navigation-entities';
import PlaceholderPreview from './placeholder-preview';
import menuItemsToBlocks from './menu-items-to-blocks';

Expand All @@ -34,76 +33,15 @@ function NavigationPlaceholder( { onCreate }, ref ) {
const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false );

const {
pages,
isResolvingPages,
hasResolvedPages,
menus,
isResolvingMenus,
hasResolvedMenus,
menuItems,
hasResolvedMenuItems,
} = useSelect(
( select ) => {
const {
getEntityRecords,
getMenus,
getMenuItems,
isResolving,
hasFinishedResolution,
} = select( coreStore );
const pagesParameters = [
'postType',
'page',
{
parent: 0,
order: 'asc',
orderby: 'id',
per_page: -1,
},
];
const menusParameters = [ { per_page: -1 } ];
const hasSelectedMenu = selectedMenu !== undefined;
const menuItemsParameters = hasSelectedMenu
? [
{
menus: selectedMenu,
per_page: -1,
},
]
: undefined;

return {
pages: getEntityRecords( ...pagesParameters ),
isResolvingPages: isResolving(
'getEntityRecords',
pagesParameters
),
hasResolvedPages: hasFinishedResolution(
'getEntityRecords',
pagesParameters
),
menus: getMenus( ...menusParameters ),
isResolvingMenus: isResolving( 'getMenus', menusParameters ),
hasResolvedMenus: hasFinishedResolution(
'getMenus',
menusParameters
),
menuItems: hasSelectedMenu
? getMenuItems( ...menuItemsParameters )
: undefined,
hasResolvedMenuItems: hasSelectedMenu
? hasFinishedResolution(
'getMenuItems',
menuItemsParameters
)
: false,
};
},
[ selectedMenu ]
);
hasPages,
hasMenus,
} = useNavigationEntities( selectedMenu );

const hasPages = !! ( hasResolvedPages && pages?.length );
const hasMenus = !! ( hasResolvedMenus && menus?.length );
const isLoading = isResolvingPages || isResolvingMenus;

const createFromMenu = useCallback( () => {
Expand Down
142 changes: 142 additions & 0 deletions packages/block-library/src/navigation/use-navigation-entities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* @typedef {Object} NavigationEntitiesData
* @property {Array|undefined} pages - a collection of WP Post entity objects of post type "Page".
* @property {boolean} isResolvingPages - indicates whether the request to fetch pages is currently resolving.
* @property {boolean} hasResolvedPages - indicates whether the request to fetch pages has finished resolving.
* @property {Array|undefined} menus - a collection of Menu entity objects.
* @property {boolean} isResolvingMenus - indicates whether the request to fetch menus is currently resolving.
* @property {boolean} hasResolvedMenus - indicates whether the request to fetch menus has finished resolving.
* @property {Array|undefined} menusItems - a collection of Menu Item entity objects for the current menuId.
* @property {boolean} hasResolvedMenuItems - indicates whether the request to fetch menuItems has finished resolving.
* @property {boolean} hasPages - indicates whether there is currently any data for pages.
* @property {boolean} hasMenus - indicates whether there is currently any data for menus.
*/

/**
* Manages fetching and resolution state for all entities required
* for the Navigation block.
*
* @param {number} menuId the menu for which to retrieve menuItem data.
* @return { NavigationEntitiesData } the entity data.
*/
export default function useNavigationEntities( menuId ) {
return {
...usePageEntities(),
...useMenuEntities(),
...useMenuItemEntities( menuId ),
};
}

function useMenuEntities() {
const { menus, isResolvingMenus, hasResolvedMenus } = useSelect(
( select ) => {
const { getMenus, isResolving, hasFinishedResolution } = select(
coreStore
);

const menusParameters = [ { per_page: -1 } ];

return {
menus: getMenus( ...menusParameters ),
isResolvingMenus: isResolving( 'getMenus', menusParameters ),
hasResolvedMenus: hasFinishedResolution(
'getMenus',
menusParameters
),
};
},
[]
);

return {
menus,
isResolvingMenus,
hasResolvedMenus,
hasMenus: !! ( hasResolvedMenus && menus?.length ),
};
}

function useMenuItemEntities( menuId ) {
const { menuItems, hasResolvedMenuItems } = useSelect(
( select ) => {
const { getMenuItems, hasFinishedResolution } = select( coreStore );

const hasSelectedMenu = menuId !== undefined;
const menuItemsParameters = hasSelectedMenu
? [
{
menus: menuId,
per_page: -1,
},
]
: undefined;

return {
menuItems: hasSelectedMenu
? getMenuItems( ...menuItemsParameters )
: undefined,
hasResolvedMenuItems: hasSelectedMenu
? hasFinishedResolution(
'getMenuItems',
menuItemsParameters
)
: false,
};
},
[ menuId ]
);

return {
menuItems,
hasResolvedMenuItems,
};
}

function usePageEntities() {
const { pages, isResolvingPages, hasResolvedPages } = useSelect(
( select ) => {
const {
getEntityRecords,
isResolving,
hasFinishedResolution,
} = select( coreStore );

const pagesParameters = [
'postType',
'page',
{
parent: 0,
order: 'asc',
orderby: 'id',
per_page: -1,
},
];

return {
pages: getEntityRecords( ...pagesParameters ) || null,
isResolvingPages: isResolving(
'getEntityRecords',
pagesParameters
),
hasResolvedPages: hasFinishedResolution(
'getEntityRecords',
pagesParameters
),
};
},
[]
);

return {
pages,
isResolvingPages,
hasResolvedPages,
hasPages: !! ( hasResolvedPages && pages?.length ),
};
}

0 comments on commit 80a2a1c

Please sign in to comment.