-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useSelect: normalise getting selectors for callbacks #31078
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here too. We're returning the entire selector list. |
||
[] | ||
); | ||
const { getBlockName } = useSelect( blockEditorStore ); | ||
const { getBlockType } = useSelect( blocksStore ); | ||
const { createSuccessNotice } = useDispatch( noticesStore ); | ||
|
||
return useCallback( ( eventType, selectedBlockClientIds ) => { | ||
|
@@ -84,7 +78,7 @@ export function useClipboardHandler() { | |
getSelectedBlockClientIds, | ||
hasMultiSelection, | ||
getSettings, | ||
} = useSelect( ( select ) => select( blockEditorStore ), [] ); | ||
} = useSelect( blockEditorStore ); | ||
const { flashBlock, removeBlocks, replaceBlocks } = useDispatch( | ||
blockEditorStore | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To have the full picture, this could also be refactored as: return {
...pick( select( blockEditorStore ), [ 'canInsertBlockType, getBlockIndex, getClientIdsOfDescendants ),
hasUploadPermissions: getSettings().mediaUpload,
}; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's doesn't solve my main problem: it's awkward to return selector functions in a mapping. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it's a workaround. I think for |
||
getBlockIndex: _getBlockIndex, | ||
getClientIdsOfDescendants: _getClientIdsOfDescendants, | ||
hasUploadPermissions: getSettings().mediaUpload, | ||
}; | ||
}, [] ); | ||
|
||
} = useSelect( blockEditorStore ); | ||
const { | ||
insertBlocks, | ||
moveBlocksToPosition, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should say something like: don't use this API while calling the selectors directly on the render function, your component won't rerender when changes happen. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This actually makes me wonder: why should we retrieve the selectors during render at all if we could also retrieve them in the callback itself? In other words, in the callbacks, we could just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The global There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would have the additional benefit of not having to pass the function as a dependency of callbacks. I'll explore this quickly in a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you misread my comment, we shouldn't do it :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, Github didn't show me your comment at the time so I didn't see it :) |
||
|
||
**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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added documentation now. I feel like we're overloading the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either way, it would be rather confusing whatever we do at this stage. We could have |
||
- _deps_ `Array`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. | ||
|
||
_Returns_ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Especially here, the benefits are clear.