-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Fix: deleting the last block triggers a focus loss. #14189
Changes from 1 commit
b4bbd1c
94f8c9d
19b0998
3c5cd95
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 |
---|---|---|
|
@@ -11,7 +11,7 @@ import { getDefaultBlockName, createBlock } from '@wordpress/blocks'; | |
/** | ||
* Internal dependencies | ||
*/ | ||
import { select } from './controls'; | ||
import { select, dispatch } from './controls'; | ||
|
||
/** | ||
* Returns an action object used in signalling that blocks state should be | ||
|
@@ -374,6 +374,23 @@ export function mergeBlocks( firstBlockClientId, secondBlockClientId ) { | |
}; | ||
} | ||
|
||
/** | ||
* Returns action objects used in signalling that the blocks corresponding to | ||
* the set of specified client IDs are to be removed. | ||
* This action does not trigger any required side effects and it is not recommended for public usage. | ||
* | ||
* @param {string|string[]} clientIds Client IDs of blocks to remove. | ||
* | ||
* @return {Object} Action object. | ||
* | ||
*/ | ||
export function __internalRemoveBlocksPure( clientIds ) { | ||
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 don't understand why this needs to exist. What was the issue with the previous 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. If we do that the yield select that appears after will return the value before the store is changed. 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 solution seems a little bit hacky, I'm probably missing something but it seemed the only way I could select from the store after the action changed the store. If there is a simpler method that I'm missing I will gladly change the code. 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.
Then if we're at the moment prior to removal, would it be enough to test that the count is An issue with this may be that there's nothing to stop me from dispatching this action with a clientId which doesn't actually exist, at which point there's still one block after calling removeBlocks 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 logic would be more complex. 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.
Yeah, in fact, re-reading your original remark, this seems like buggy behavior to me. The result of
|
||
return { | ||
type: 'REMOVE_BLOCKS', | ||
clientIds, | ||
}; | ||
} | ||
|
||
/** | ||
* Yields action objects used in signalling that the blocks corresponding to | ||
* the set of specified client IDs are to be removed. | ||
|
@@ -386,13 +403,26 @@ export function* removeBlocks( clientIds, selectPrevious = true ) { | |
clientIds = castArray( clientIds ); | ||
|
||
if ( selectPrevious ) { | ||
yield selectPreviousBlock( clientIds[ 0 ] ); | ||
yield dispatch( | ||
'core/block-editor', | ||
'selectPreviousBlock', | ||
clientIds[ 0 ] | ||
); | ||
} | ||
|
||
yield { | ||
type: 'REMOVE_BLOCKS', | ||
yield dispatch( | ||
'core/block-editor', | ||
'__internalRemoveBlocksPure', | ||
clientIds, | ||
}; | ||
); | ||
|
||
const count = yield select( | ||
'core/block-editor', | ||
'getBlockCount', | ||
); | ||
if ( count === 0 ) { | ||
yield insertDefaultBlock(); | ||
} | ||
} | ||
|
||
/** | ||
|
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.
This naming convention is not standard.
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.
Normally for experimental functions we use __experimental I followed something similar and used __internal as a prefix, I was not aware we have a were following a standard for this. What you think would be the best prefix for a case like this?
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.
They're documented here:
https://github.com/WordPress/gutenberg/blob/535e0752051957f3e6ab7aca2e71e99ceffc9a6f/docs/contributors/coding-guidelines.md#experimental-apis
I raise as a concern of: Introducing new vocabulary contributes to lack of cohesiveness and understanding when not consciously agreed upon, documented, and used consistency.
For example, it's not clear to me what differentiates an "internal" and "unstable" function. The problem admittedly already exists to an extent between unstable and experimental, and its confusion has prompted more than a few conversations.
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.
I'd rather see the function not exist at all, if possible, per the other conversation thread. If needing to act before / after a dispatch takes effect is an issue, it's quite unlikely that this will be isolated, and this pattern does not seem like one which would scale well.