-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Propose useEntityRecords (experimental) #38782
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
Changes from all commits
5654efa
6b0e67c
2246075
2a93ed2
179e77f
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 |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| /** | ||
| * WordPress dependencies | ||
| */ | ||
| import triggerFetch from '@wordpress/api-fetch'; | ||
| import { createRegistry, RegistryProvider } from '@wordpress/data'; | ||
|
|
||
| jest.mock( '@wordpress/api-fetch' ); | ||
|
|
||
| /** | ||
| * External dependencies | ||
| */ | ||
| import { act, render } from '@testing-library/react'; | ||
|
|
||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import { store as coreDataStore } from '../../index'; | ||
| import useEntityRecords from '../use-entity-records'; | ||
|
|
||
| describe( 'useEntityRecords', () => { | ||
| let registry; | ||
| beforeEach( () => { | ||
| jest.useFakeTimers(); | ||
|
|
||
| registry = createRegistry(); | ||
| registry.register( coreDataStore ); | ||
| } ); | ||
|
|
||
| afterEach( () => { | ||
| jest.runOnlyPendingTimers(); | ||
| jest.useRealTimers(); | ||
| } ); | ||
|
|
||
| const TEST_RECORDS = [ | ||
| { id: 1, hello: 'world1' }, | ||
| { id: 2, hello: 'world2' }, | ||
| { id: 3, hello: 'world3' }, | ||
| ]; | ||
|
|
||
| it( 'resolves the entity records when missing from the state', async () => { | ||
| // Provide response | ||
| triggerFetch.mockImplementation( () => TEST_RECORDS ); | ||
|
|
||
| let data; | ||
| const TestComponent = () => { | ||
| data = useEntityRecords( 'root', 'widget', { status: 'draft' } ); | ||
| return <div />; | ||
| }; | ||
| render( | ||
| <RegistryProvider value={ registry }> | ||
| <TestComponent /> | ||
| </RegistryProvider> | ||
| ); | ||
|
|
||
| expect( data ).toEqual( { | ||
| records: null, | ||
| hasResolved: false, | ||
| isResolving: false, | ||
| status: 'IDLE', | ||
| } ); | ||
|
|
||
| await act( async () => { | ||
| jest.advanceTimersByTime( 1 ); | ||
| } ); | ||
|
|
||
| // Fetch request should have been issued | ||
| expect( triggerFetch ).toHaveBeenCalledWith( { | ||
| path: '/wp/v2/widgets?context=edit&status=draft', | ||
| } ); | ||
|
|
||
| expect( data ).toEqual( { | ||
| records: TEST_RECORDS, | ||
| hasResolved: true, | ||
| isResolving: false, | ||
| status: 'SUCCESS', | ||
| } ); | ||
| } ); | ||
| } ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import useQuerySelect from './use-query-select'; | ||
| import { store as coreStore } from '../'; | ||
| import { Status } from './constants'; | ||
|
|
||
| interface EntityRecordsResolution< RecordType > { | ||
| /** The requested entity record */ | ||
| records: RecordType[] | null; | ||
|
|
||
| /** | ||
| * Is the record still being resolved? | ||
| */ | ||
| isResolving: boolean; | ||
|
|
||
| /** | ||
| * Is the record resolved by now? | ||
| */ | ||
| hasResolved: boolean; | ||
|
|
||
| /** Resolution status */ | ||
| status: Status; | ||
| } | ||
|
|
||
| /** | ||
| * Resolves the specified entity records. | ||
| * | ||
| * @param kind Kind of the requested entities. | ||
| * @param name Name of the requested entities. | ||
adamziel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * @param queryArgs HTTP query for the requested entities. | ||
adamziel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * | ||
| * @example | ||
| * ```js | ||
| * import { useEntityRecord } from '@wordpress/core-data'; | ||
| * | ||
| * function PageTitlesList() { | ||
| * const { records, isResolving } = useEntityRecords( 'postType', 'page' ); | ||
| * | ||
| * if ( isResolving ) { | ||
| * return 'Loading...'; | ||
| * } | ||
| * | ||
| * return ( | ||
| * <ul> | ||
| * {records.map(( page ) => ( | ||
| * <li>{ page.title }</li> | ||
| * ))} | ||
| * </ul> | ||
| * ); | ||
| * } | ||
| * | ||
| * // Rendered in the application: | ||
| * // <PageTitlesList /> | ||
| * ``` | ||
| * | ||
| * In the above example, when `PageTitlesList` is rendered into an | ||
| * application, the list of records and the resolution details will be retrieved from | ||
| * the store state using `getEntityRecords()`, or resolved if missing. | ||
| * | ||
| * @return {EntityRecordsResolution<RecordType>} Entity records data. | ||
adamziel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * @template RecordType | ||
| */ | ||
| export default function __experimentalUseEntityRecords< RecordType >( | ||
| kind: string, | ||
| name: string, | ||
| queryArgs: unknown = {} | ||
|
Member
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. how hard would it be to surface a type of Given that these are just passed through we might be able to reuse the types from interface EntityRecordHook<RecordType> {
(kind: string; name: string; queryArgs: HttpQuery) => EntityRecordResolution<RecordType>;
}
// use-entity-record.ts
export default useEntityRecord: EntityRecordHook = (kind, name, queryArgs) => …;
// use-entity-records.ts
export default useEntityRecords: EntityRecordHook = …EntityRecordHook.mov
Contributor
Author
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.
Good idea! The
It doesn't match, though 😅 it is |
||
| ): EntityRecordsResolution< RecordType > { | ||
| const { data: records, ...rest } = useQuerySelect( | ||
| ( query ) => | ||
| query( coreStore ).getEntityRecords( kind, name, queryArgs ), | ||
| [ kind, name, queryArgs ] | ||
| ); | ||
|
|
||
| return { | ||
| records, | ||
| ...rest, | ||
| }; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.