-
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
[core-data] throwOnError option for saveEntityRecord and deleteEntityRecord actions #39258
Conversation
Size Change: +2 B (0%) Total Size: 1.16 MB
ℹ️ View Unchanged
|
Looking at the resulting code, somehow the more verbose code seems more readable? It's like a story. |
You didn't used to be able to I like the idea, but I don't find the API to be very intuitive if I'm honest. That is, when I read the code, I don't instantly know what it will do. What do you think about a param? await saveEditedEntityRecord(
'postType',
template.type,
template.id,
{ throwOnError: true }
); |
I'm not familiar with the existing codebase that uses the flow that is discussed in this PR, but I must admit that the proposal from @noisysocks in #39258 (comment) sounds reasonable. This way we can reduce the boilerplate code and we still leave the choice to the developer how it should be handled. The challenge for public APIs is that you rather want to minimize the number of methods exposed to optimize for the most common usage and easier discovery. This goes in contrast to the consuming projects where a new method might help to make the code more readable.
Thank you for sharing the full context and your thoughts process. It really helps to understand how you arrived at the final proposal and more importantly leaves a great archive that we can use in the future when evolving all those APIs around entities. |
I like it much better @noisysocks, thank you! I just updated this PR accordingly.
My pleasure @gziolo ! I suspected that sharing just the final conclusion wouldn't be quite enough to explain the rationale here, I'm glad that was useful! I might start doing it more often when reasonable 🤔 |
We can also expose I guess for |
The e2e failures are unrelated to this PR, see https://core.trac.wordpress.org/ticket/55367 |
packages/core-data/README.md
Outdated
@@ -70,6 +70,7 @@ _Parameters_ | |||
- _query_ `?Object`: Special query parameters for the DELETE API call. | |||
- _options_ `[Object]`: Delete options. | |||
- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise. | |||
- _options.throwOnError_ `[boolean]`: If false, this action suppresses all the exceptions. |
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.
Aside: I think @michalczaplinski raised it in other places that it's confusing that the same APIs are documented in two places - here and in docs/reference-guides/data/data-core.md.
It'd be a good follow-up.
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.
The fix is beyond this PR, but I fully agree
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.
Follow-up = new PR. So we are on the same page 😄
291d425
to
1b92f4d
Compare
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.
Mostly looks good! Just a small concern regarding falsy error values.
packages/core-data/src/actions.js
Outdated
@@ -273,6 +275,10 @@ export const deleteEntityRecord = ( | |||
error, | |||
} ); | |||
|
|||
if ( error && throwOnError ) { |
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.
What if error
is undefined
or null
or 0
or any falsy value? Even though it's an edge case, it should still throw such error 😅. I guess we'll need a flag like hasError
to determine if it reaches the catch
clause or not.
(Would be awesome if there's a test case for it too, but it's a nitpick.)
e084468
to
761c82b
Compare
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.
LGTM 👍
b9104fb
to
ab24ce7
Compare
ab24ce7
to
8561fc9
Compare
…ngside usage examples
Co-authored-by: Greg Ziółkowski <[email protected]>
8561fc9
to
9f847af
Compare
Description
This is a continuation of Entity records hooks.
An original idea was to make creating, editing, and deleting entity records easier by introducing a specialized convenience wrapper such as
useEntityMutation
:The rationale – that the full flow is not easy to figure out, confusing at times, and it is easy to omit a part or two. For example, to edit a record, save it, and display a progress indicator and any error information, you need at least the following information and actions:
Diving deeper, we realized that it is hard to distinguish between creating and updating records when both use-cases are crammed within a single
useEntityMutation
hook.In this PR, I explored three smaller hooks called
useEntityRecordCreate
,useEntityRecordUpdate
, anduseEntityRecordDelete
. See the relevant commit.However, it quickly occurred to me that we only rely on all these selectors because we do not embrace the full power of promises. For example, the Gutenberg codebase commonly relies on the following pattern:
This looks a whole lot like what we do in PHP:
What if we used promises instead? Even better, what if we ditched the hooks and used the promises right in the store so that other stores could benefit from that as well? And so this is the proposal this PR makes:
It takes care of:
isSavingEntityRecord
may still be used when needed or more convenient.Different angles
Re-throwing errors is different than having a convenience wrapper for actions like
editEntityRecord
,saveEditedEntityRecord
,saveEntityRecord
and thegetEditedEntityRecord
selector. Perhaps that's where a hook would actually shine:However, given the "throwing" actions, accessing
error
andisCreating/isSaving/isRemoving
would not be needed as often, which leaves us with just:Which doesn't do much for creating and removing records, so we could also ditch these hooks and settle only for the
useEntityRecordEdit
hook:I'm interested in your thoughts about all that.
cc @gziolo @kevin940726 @getdave @noisysocks @scruffian @draganescu