Simplified data access with new React hooks in WordPress 6.1

The @wordpress/core-data JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. package in 6.1 ships new ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. that make accessing WordPress data easier than before.

useEntityRecords

With useEntityRecords developers, can fetch a list of records with a single hook call:

useEntityRecords( 'postType', 'page' )

Below is what it looks like when used in a React component:

import { useEntityRecord } from '@wordpress/core-data';
 
function PageTitlesList() {
   const pages = useEntityRecords( 'postType', 'page' );
 
   if ( pages.isResolving ) {
      return 'Loading...';
   }
 
   return (
      <ul>
         {pages.records.map(( page ) => (
            <li>{ page.title }</li>
         ))}
      </ul>
   );
};
 
// Rendered in the application:
// <PageTitlesList />

In the above example when PageTitlesList is rendered, the list of records and the resolution details will be retrieved from the store state using getEntityRecords(), or resolved if missing.

The useEntityRecords accepts four arguments:

  • kind (string) – Kind of the entity, e.g. root or a postType.
  • name (string) – Name of the entity, e.g. plugin or a post.
  • queryArgs (object) – Optional HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. query to pass to the requested APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. endpoint, e.g. { "per_page": 10 }
  • options (object) – Optional hook options. Currently, the only supported option is enabled and determines whether the records will be requested.

It returns an object with the following properties:

  • records (array) – The requested entity records
  • isResolving (boolean) – Are these records being resolved at the moment?
  • hasResolved (boolean) – Have these records resolved already?
  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR

useEntityRecord:

Developers can retrieve a single record using the useEntityRecord hook:

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

function PageTitleDisplay( { id } ) {
	const page = useEntityRecord( 'postType', 'page', id );

	if ( page.isResolving ) {
		return 'Loading...';
	}

	return page.title;
}

// Rendered in the application:
// <PageTitleDisplay id={ 13 } />

In the above example, when PageTitleDisplay is rendered, the page and the resolution details will be retrieved from the store state using getEntityRecord(), or resolved if missing.

The useEntityRecord hook accepts four arguments:

  • kind (string) – Kind of the entity, e.g. root or a postType.
  • name (string) – Name of the entity, e.g. plugin or a post.
  • recordId (string|number) – The ID of the requested entity record.
  • options (object) – Optional hook options. Currently, the only supported option is enabled and determines whether the records will be requested.

It returns an object with the following properties:

  • record (object|null) – The resolved entity record.
  • isResolving (boolean) – Is the record being resolved at the moment?
  • hasResolved (boolean) – Has the record already resolved already?
  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR.
  • hasEdits (boolean) – Does the record have any in-browser edits?
  • editedRecord (object|null) – The record with any in-browser edits applied.
  • edit (function) – Applies the in-browser edits to the edited entity record.
  • save (function) – Persist the in-browser edits to the server.

Below is an example showcasing the editing capabilities provided by useEntityRecord:

import { useDispatch } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { TextControl } from '@wordpress/components';
import { store as noticeStore } from '@wordpress/notices';
import { useEntityRecord } from '@wordpress/core-data';
 
function PageRenameForm( { id } ) {
 	const page = useEntityRecord( 'postType', 'page', id );
 	const { createSuccessNotice, createErrorNotice } =
 		useDispatch( noticeStore );
 
 	const setTitle = useCallback( ( title ) => {
 		page.edit( { title } );
 	}, [ page.edit ] );
 
 	if ( page.isResolving ) {
 		return 'Loading...';
 	}
 
 	async function onRename( event ) {
 		event.preventDefault();
 		try {
 			await page.save();
 			createSuccessNotice( __( 'Page renamed.' ), {
 				type: 'snackbar',
 			} );
 		} catch ( error ) {
 			createErrorNotice( error.message, { type: 'snackbar' } );
 		}
 	}
 
 	return (
		<form onSubmit={ onRename }>
			<TextControl
				label={ __( 'Name' ) }
				value={ page.editedRecord.title }
				onChange={ setTitle }
			/>
			<button type="submit">{ __( 'Save' ) }</button>
		</form>
 	);
}
// Rendered in the application:
// <PageRenameForm id={ 1 } />

In the above example, updating and saving the page title is handled via the edit() and save() mutation helpers provided by useEntityRecord();

useResourcePermissions

Developers can check the current user’s permissions using the useResourcePermissions hook:

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

function Page({ pageId }) {
	const pagePermissions = useResourcePermissions( 'pages', pageId );

	if ( pagePermissions.isResolving ) {
		return 'Loading ...';
	}

	return (
        <div>
			{pagePermissions.canCreate
				? (+ Create a new page)
				: false}
			{pagePermissions.canUpdate
				? (Edit page)
				: false}
			{pagePermissions.canDelete
				? (Delete page)
				: false}
			// ...
        </div>
	);
}

// Rendered in the application:
// <Page pageId={ 15 } />

In the above example when the Page is rendered, the appropriate record-level page permissions and the resolution details will be retrieved from the store state using the canUser() selector, or resolved if missing.

In the following example, the PagesList component requests permissions for the pages collection and not a specific page record:

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

function PagesList() {
   const pagesPermissions = useResourcePermissions( 'pages' );

   if ( pagesPermissions.isResolving ) {
      return 'Loading ...';
   }

   return (
      <div>
         {pagesPermissions.canCreate
            ? (+ Create a new page)
            : false }
         // ...
      </div>
   );
}

// Rendered in the application:
// <PagesList />

The useResourcePermissions hook accepts two arguments:

  • resource (string) – The resource in question, e.g., media.
  • id (string|number) – Optional ID of a specific resource entry, e.g., 10.

It returns an object with the following properties:

  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR
  • isResolving (boolean) – Is the record being resolved at the moment?
  • hasResolved (boolean) – Has the record already resolved?
  • create (boolean) – Can the current user create new resources of this type?
  • read (boolean) – Can the current user read resources of this type?
  • update (boolean) – Only if id is provided. Can the current user update the requested resource?
  • delete (boolean) – Only if id is provided. Can the current user delete the requested resource?

Documentation: @wordpress/core-data packages

Props for review @bph, @gziolo, and @webcommsat

#6-1, #wordpress-data, #dev-notes, #dev-notes-6-1, #editor