Skip to content

Commit

Permalink
useSelect: normalise getting selectors for callbacks (#31078)
Browse files Browse the repository at this point in the history
* useSelect: normalise getting selectors for callbacks

* Add docs

* Address docs feedback

* Clean up a bit
  • Loading branch information
ellatrix authored and youknowriad committed Apr 29, 2021
1 parent 870393a commit b47f295
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,40 +48,6 @@ function isWindows() {
return window.navigator.platform.indexOf( 'Win' ) > -1;
}

function selector( select ) {
const {
getSelectedBlockClientId,
getMultiSelectedBlocksEndClientId,
getPreviousBlockClientId,
getNextBlockClientId,
hasBlockMovingClientId,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
canInsertBlockType,
getBlockName,
} = select( blockEditorStore );

const selectedBlockClientId = getSelectedBlockClientId();
const selectionEndClientId = getMultiSelectedBlocksEndClientId();

return {
selectedBlockClientId,
selectionBeforeEndClientId: getPreviousBlockClientId(
selectionEndClientId || selectedBlockClientId
),
selectionAfterEndClientId: getNextBlockClientId(
selectionEndClientId || selectedBlockClientId
),
hasBlockMovingClientId,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
canInsertBlockType,
getBlockName,
};
}

/**
* Block selection button component, displaying the label of the block. If the block
* descends from a root block, a button is displayed enabling the user to select
Expand Down Expand Up @@ -134,14 +100,15 @@ function BlockSelectionButton( { clientId, rootClientId, blockElement } ) {
}, [] );

const {
selectedBlockClientId,
selectionBeforeEndClientId,
selectionAfterEndClientId,
hasBlockMovingClientId,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
} = useSelect( selector, [] );
getSelectedBlockClientId,
getMultiSelectedBlocksEndClientId,
getPreviousBlockClientId,
getNextBlockClientId,
} = useSelect( blockEditorStore );
const {
selectBlock,
clearSelectedBlock,
Expand All @@ -167,6 +134,15 @@ function BlockSelectionButton( { clientId, rootClientId, blockElement } ) {
return;
}

const selectedBlockClientId = getSelectedBlockClientId();
const selectionEndClientId = getMultiSelectedBlocksEndClientId();
const selectionBeforeEndClientId = getPreviousBlockClientId(
selectionEndClientId || selectedBlockClientId
);
const selectionAfterEndClientId = getNextBlockClientId(
selectionEndClientId || selectedBlockClientId
);

const navigateUp = ( isTab && isShift ) || isUp;
const navigateDown = ( isTab && ! isShift ) || isDown;
// Move out of current nesting level (no effect if at root level).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,27 +272,25 @@ export default function useInsertionPoint( ref ) {
isInserterVisible,
selectedClientId,
selectedRootClientId,
getBlockListSettings,
} = useSelect( ( select ) => {
const {
isMultiSelecting: _isMultiSelecting,
isBlockInsertionPointVisible,
getBlockInsertionPoint,
getBlockOrder,
getBlockListSettings: _getBlockListSettings,
} = select( blockEditorStore );

const insertionPoint = getBlockInsertionPoint();
const order = getBlockOrder( insertionPoint.rootClientId );

return {
getBlockListSettings: _getBlockListSettings,
isMultiSelecting: _isMultiSelecting(),
isInserterVisible: isBlockInsertionPointVisible(),
selectedClientId: order[ insertionPoint.index - 1 ],
selectedRootClientId: insertionPoint.rootClientId,
};
}, [] );
const { getBlockListSettings } = useSelect( blockEditorStore );

const onMouseMove = useCallback(
( event ) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,7 @@ export default function useBlockNavigationDropZone() {
getBlockCount,
getDraggedBlockClientIds,
canInsertBlocks,
} = useSelect( ( select ) => {
const selectors = select( blockEditorStore );
return {
canInsertBlocks: selectors.canInsertBlocks,
getBlockRootClientId: selectors.getBlockRootClientId,
getBlockIndex: selectors.getBlockIndex,
getBlockCount: selectors.getBlockCount,
getDraggedBlockClientIds: selectors.getDraggedBlockClientIds,
};
}, [] );
} = useSelect( blockEditorStore );
const [ target, setTarget ] = useState();
const { rootClientId: targetRootClientId, blockIndex: targetBlockIndex } =
target || {};
Expand Down
12 changes: 3 additions & 9 deletions packages/block-editor/src/components/copy-handler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,8 @@ import { getPasteEventData } from '../../utils/get-paste-event-data';
import { store as blockEditorStore } from '../../store';

export function useNotifyCopy() {
const { getBlockName } = useSelect(
( select ) => select( blockEditorStore ),
[]
);
const { getBlockType } = useSelect(
( select ) => select( blocksStore ),
[]
);
const { getBlockName } = useSelect( blockEditorStore );
const { getBlockType } = useSelect( blocksStore );
const { createSuccessNotice } = useDispatch( noticesStore );

return useCallback( ( eventType, selectedBlockClientIds ) => {
Expand Down Expand Up @@ -84,7 +78,7 @@ export function useClipboardHandler() {
getSelectedBlockClientIds,
hasMultiSelection,
getSettings,
} = useSelect( ( select ) => select( blockEditorStore ), [] );
} = useSelect( blockEditorStore );
const { flashBlock, removeBlocks, replaceBlocks } = useDispatch(
blockEditorStore
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ export default function useInnerBlockTemplateSync(
templateLock,
templateInsertUpdatesSelection
) {
const getSelectedBlocksInitialCaretPosition = useSelect(
( select ) =>
select( blockEditorStore ).getSelectedBlocksInitialCaretPosition,
[]
const { getSelectedBlocksInitialCaretPosition } = useSelect(
blockEditorStore
);
const { replaceInnerBlocks } = useDispatch( blockEditorStore );
const innerBlocks = useSelect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,10 @@ function useInsertionPoint( {
onSelect,
shouldFocusBlock = true,
} ) {
const {
destinationRootClientId,
destinationIndex,
getSelectedBlock,
} = useSelect(
const { getSelectedBlock } = useSelect( blockEditorStore );
const { destinationRootClientId, destinationIndex } = useSelect(
( select ) => {
const {
getSelectedBlock: _getSelectedBlock,
getBlockIndex,
getBlockOrder,
getBlockInsertionPoint,
Expand Down Expand Up @@ -90,7 +86,6 @@ function useInsertionPoint( {
}

return {
getSelectedBlock: _getSelectedBlock,
destinationRootClientId: _destinationRootClientId,
destinationIndex: _destinationIndex,
};
Expand Down
18 changes: 5 additions & 13 deletions packages/block-editor/src/components/inserter/menu.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,11 @@ function InserterMenu( {
insertDefaultBlock,
} = useDispatch( blockEditorStore );

const {
items,
destinationRootClientId,
getBlockOrder,
getBlockCount,
canInsertBlockType,
} = useSelect( ( select ) => {
const { items, destinationRootClientId } = useSelect( ( select ) => {
const {
getInserterItems,
getBlockRootClientId,
getBlockSelectionEnd,
...selectBlockEditorStore
} = select( blockEditorStore );

let targetRootClientId = rootClientId;
Expand All @@ -78,13 +71,12 @@ function InserterMenu( {
return {
items: getInserterItems( targetRootClientId ),
destinationRootClientId: targetRootClientId,
getBlockOrder: selectBlockEditorStore.getBlockOrder,
getBlockCount: selectBlockEditorStore.getBlockCount,
canInsertBlockType: selectBlockEditorStore.canInsertBlockType,
};
} );

const { getBlockType } = useSelect( ( select ) => select( blocksStore ) );
const { getBlockOrder, getBlockCount, canInsertBlockType } = useSelect(
blockEditorStore
);
const { getBlockType } = useSelect( blocksStore );

useEffect( () => {
// Show/Hide insertion point on Mount/Dismount
Expand Down
22 changes: 5 additions & 17 deletions packages/block-editor/src/components/use-on-block-drop/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,27 +212,15 @@ export function onHTMLDrop(
* @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.
*/
export default function useOnBlockDrop( targetRootClientId, targetBlockIndex ) {
const hasUploadPermissions = useSelect(
( select ) => select( blockEditorStore ).getSettings().mediaUpload,
[]
);
const {
canInsertBlockType,
getBlockIndex,
getClientIdsOfDescendants,
hasUploadPermissions,
} = useSelect( ( select ) => {
const {
canInsertBlockType: _canInsertBlockType,
getBlockIndex: _getBlockIndex,
getClientIdsOfDescendants: _getClientIdsOfDescendants,
getSettings,
} = select( blockEditorStore );

return {
canInsertBlockType: _canInsertBlockType,
getBlockIndex: _getBlockIndex,
getClientIdsOfDescendants: _getClientIdsOfDescendants,
hasUploadPermissions: getSettings().mediaUpload,
};
}, [] );

} = useSelect( blockEditorStore );
const {
insertBlocks,
moveBlocksToPosition,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function selector( select ) {
isMultiSelecting,
getMultiSelectedBlockClientIds,
hasMultiSelection,
getBlockParents,
getSelectedBlockClientId,
} = select( blockEditorStore );

Expand All @@ -51,7 +50,6 @@ function selector( select ) {
isMultiSelecting: isMultiSelecting(),
multiSelectedBlockClientIds: getMultiSelectedBlockClientIds(),
hasMultiSelection: hasMultiSelection(),
getBlockParents,
selectedBlockClientId: getSelectedBlockClientId(),
};
}
Expand All @@ -74,9 +72,9 @@ export default function useMultiSelection( ref ) {
isMultiSelecting,
multiSelectedBlockClientIds,
hasMultiSelection,
getBlockParents,
selectedBlockClientId,
} = useSelect( selector, [] );
const { getBlockParents } = useSelect( blockEditorStore );
const {
startMultiSelect,
stopMultiSelect,
Expand Down
6 changes: 2 additions & 4 deletions packages/block-library/src/buttons/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ export default function ButtonsEdit( {
const [ maxWidth, setMaxWidth ] = useState( 0 );
const { marginLeft: spacing } = styles.spacing;

const { getBlockOrder, isInnerButtonSelected, shouldDelete } = useSelect(
const { isInnerButtonSelected, shouldDelete } = useSelect(
( select ) => {
const {
getBlockCount,
getBlockOrder: _getBlockOrder,
getBlockParents,
getSelectedBlockClientId,
} = select( blockEditorStore );
Expand All @@ -56,7 +55,6 @@ export default function ButtonsEdit( {
);

return {
getBlockOrder: _getBlockOrder,
isInnerButtonSelected: selectedBlockParents[ 0 ] === clientId,
// The purpose of `shouldDelete` check is giving the ability to
// pass to mobile toolbar function called `onDelete` which removes
Expand All @@ -67,7 +65,7 @@ export default function ButtonsEdit( {
},
[ clientId ]
);

const { getBlockOrder } = useSelect( blockEditorStore );
const { insertBlock, removeBlock, selectBlock } = useDispatch(
blockEditorStore
);
Expand Down
21 changes: 20 additions & 1 deletion packages/data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,28 @@ any price in the state for that currency is retrieved. If the currency prop
doesn't change and other props are passed in that do change, the price will
not change because the dependency is just the currency.

When data is only used in an event callback, the data should not be retrieved
on render, so it may be useful to get the selectors function instead.

**Don't use `useSelect` this way when calling the selectors in the render
function because your component won't re-render on a data change.**

```js
import { useSelect } from '@wordpress/data';

function Paste( { children } ) {
const { getSettings } = useSelect( 'my-shop' );
function onPaste() {
// Do something with the settings.
const settings = getSettings();
}
return <div onPaste={ onPaste }>{ children }</div>;
}
```

_Parameters_

- _\_mapSelect_ `Function`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument.
- _\_mapSelect_ `Function|WPDataStore|string`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree.
- _deps_ `Array`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change.

_Returns_
Expand Down
Loading

0 comments on commit b47f295

Please sign in to comment.