diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 8b1f9a41e3378..3d310092669ca 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -202,6 +202,21 @@ _Returns_ - `?Object`: The entity record's non transient edits. +# **getEntityRecordNoResolver** + +Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity from the API if the entity record isn't available in the local state. + +_Parameters_ + +- _state_ `Object`: State tree +- _kind_ `string`: Entity kind. +- _name_ `string`: Entity name. +- _key_ `number`: Record's key + +_Returns_ + +- `?Object`: Record. + # **getEntityRecords** Returns the Entity's records. diff --git a/packages/core-data/README.md b/packages/core-data/README.md index c1e1c27691fe8..ca399d641821d 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -415,6 +415,21 @@ _Returns_ - `?Object`: The entity record's non transient edits. +# **getEntityRecordNoResolver** + +Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity from the API if the entity record isn't available in the local state. + +_Parameters_ + +- _state_ `Object`: State tree +- _kind_ `string`: Entity kind. +- _name_ `string`: Entity name. +- _key_ `number`: Record's key + +_Returns_ + +- `?Object`: Record. + # **getEntityRecords** Returns the Entity's records. diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 3a08117082084..681d4000998f6 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -357,11 +357,10 @@ export function* saveEntityRecord( } } - // We perform an optimistic update here to clear all the edits that - // will be persisted so that if the server filters them, the new - // filtered values are always accepted. + // Get the full local version of the record before the update, + // to merge it with the edits and then propagate it to subscribers persistedEntity = yield select( - 'getEntityRecord', + 'getEntityRecordNoResolver', kind, name, recordId diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index a4ea47ac8c745..495ebbbf94d79 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -107,6 +107,20 @@ export function getEntityRecord( state, kind, name, key ) { return get( state.entities.data, [ kind, name, 'queriedData', 'items', key ] ); } +/** + * Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity from the API if the entity record isn't available in the local state. + * + * @param {Object} state State tree + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number} key Record's key + * + * @return {Object?} Record. + */ +export function getEntityRecordNoResolver( state, kind, name, key ) { + return getEntityRecord( state, kind, name, key ); +} + /** * Returns the entity's record object by key, * with its attributes mapped to their raw values. diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index ffcee0efbca50..23e9463b03ebb 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -41,8 +41,11 @@ describe( 'saveEntityRecord', () => { expect( fulfillment.next( entities ).value.type ).toBe( 'SAVE_ENTITY_RECORD_START' ); + + // Should select getEntityRecordNoResolver selector (as opposed to getEntityRecord) + // see https://github.com/WordPress/gutenberg/pull/19752#discussion_r368498318. expect( fulfillment.next().value.type ).toBe( 'SELECT' ); - expect( fulfillment.next().value.type ).toBe( 'SELECT' ); + expect( fulfillment.next().value.selectorName ).toBe( 'getEntityRecordNoResolver' ); expect( fulfillment.next().value.type ).toBe( 'SELECT' ); expect( fulfillment.next().value.type ).toBe( 'RECEIVE_ITEMS' ); const { value: apiFetchAction } = fulfillment.next( {} ); diff --git a/packages/core-data/src/test/selectors.js b/packages/core-data/src/test/selectors.js index ae75557d40f1a..07a2540d6dd4e 100644 --- a/packages/core-data/src/test/selectors.js +++ b/packages/core-data/src/test/selectors.js @@ -8,6 +8,7 @@ import deepFreeze from 'deep-freeze'; */ import { getEntityRecord, + getEntityRecordNoResolver, getEntityRecords, getEntityRecordChangesByRecord, getEntityRecordNonTransientEdits, @@ -20,7 +21,11 @@ import { getReferenceByDistinctEdits, } from '../selectors'; -describe( 'getEntityRecord', () => { +// getEntityRecord and getEntityRecordNoResolver selectors share the same tests +describe.each( [ + [ getEntityRecord ], + [ getEntityRecordNoResolver ], +] )( '%p', ( selector ) => { it( 'should return undefined for unknown record’s key', () => { const state = deepFreeze( { entities: { @@ -36,7 +41,7 @@ describe( 'getEntityRecord', () => { }, }, } ); - expect( getEntityRecord( state, 'root', 'postType', 'post' ) ).toBe( undefined ); + expect( selector( state, 'root', 'postType', 'post' ) ).toBe( undefined ); } ); it( 'should return a record by key', () => { @@ -56,7 +61,9 @@ describe( 'getEntityRecord', () => { }, }, } ); - expect( getEntityRecord( state, 'root', 'postType', 'post' ) ).toEqual( { slug: 'post' } ); + expect( selector( state, 'root', 'postType', 'post' ) ).toEqual( { + slug: 'post', + } ); } ); } );