Skip to content

Core Data: Allow useEntityProp setter to accept an updater function#70877

Open
Adi-ty wants to merge 3 commits intoWordPress:trunkfrom
Adi-ty:feat/use-entity-prop-updater-function
Open

Core Data: Allow useEntityProp setter to accept an updater function#70877
Adi-ty wants to merge 3 commits intoWordPress:trunkfrom
Adi-ty:feat/use-entity-prop-updater-function

Conversation

@Adi-ty
Copy link
Contributor

@Adi-ty Adi-ty commented Jul 23, 2025

What?

This PR implements updater function support for the useEntityProp hook, addressing the stale closure issue.

Closes #70748

Why?

When using useEntityProp in async functions, stale closures can lead to data loss. The existing setter requires a static value, which can become outdated during async operations.

How?

Updated Hook Logic: Modified the setValue function to accept updater functions. If newValue is a function, it will receive the current state. This prevents stale data issues by ensuring the setter captures the most recent state when invoked.

Testing Instructions

  1. Create a test component that uses useEntityProp:
   const [meta, setMeta] = useEntityProp('postType', 'post', 'meta', postId);
  1. Test backward compatibility - verify static values still work:
   setMeta({ key: 'static value' }); 
  1. Test new updater function - verify the new functionality:
   setMeta((currentMeta) => ({ ...currentMeta, newKey: 'value' }));
@Adi-ty Adi-ty marked this pull request as ready for review July 25, 2025 11:00
@Adi-ty Adi-ty requested a review from nerrad as a code owner July 25, 2025 11:00
@github-actions
Copy link

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Type-related labels to choose from: [Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core, Gutenberg Plugin.
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions
Copy link

github-actions bot commented Jul 25, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: Adi-ty <iamadisingh@git.wordpress.org>
Co-authored-by: cr0ybot <cr0ybot@git.wordpress.org>
Co-authored-by: iansvo <iansvo@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

_Returns_

- `[*, Function, *]`: An array where the first item is the property value, the second is the setter and the third is the full value object from REST API containing more information like `raw`, `rendered` and `protected` props.
- `[*, Function, *]`: An array where the first item is the property value, the second is the setter (which accepts either a value or an updater function) and the third is the full value object from REST API containing more information like `raw`, `rendered` and `protected` props.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is perhaps a little vague for someone that doesn't know what an updater function usually looks like. A "Usage" section like useEntityRecord has would be really nice.

I would suggest something like the following:

import { useEntityProp } from '@wordpress/core-data';

function MetaUpdater( { postType, postId } ) {
	const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta', postId );

	const handleSyncUpdate = () => {
		const result = syncTask();

		// Use setter with a static value:
		setMeta( { ...meta, taskKey: result } );
	};

	const handleAsyncUpdate = async () => {
		const result = await asyncTask();

		// Use setter with an updater function:
		setMeta( ( currentMeta ) => { ...currentMeta, taskKey: result } );
	};
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cr0ybot Thank you for the feedback! I've added your suggested usage section.

@Adi-ty Adi-ty requested a review from cr0ybot July 28, 2025 05:26
@im3dabasia im3dabasia added [Type] Enhancement A suggestion for improvement. [Package] Core data /packages/core-data labels Aug 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Core data /packages/core-data [Type] Enhancement A suggestion for improvement.

3 participants